Цифровые автоматы в классах по qwone

Logik
Онлайн
Зарегистрирован: 05.08.2014

Arhat109-2 пишет:

Воспользуйтесь этим драйвером I2C, ....

Не ведись квон! Это провокация, там классов нет! И даже без шаблонов. Такой код недопустим, работать будет не стабильно, он не масштабируется и его поддержка невозможна. Ему здесь не место!

bwn
Offline
Зарегистрирован: 25.08.2014

Logik пишет:

Arhat109-2 пишет:

Воспользуйтесь этим драйвером I2C, ....

Не ведись квон! Это провокация, там классов нет! И даже без шаблонов. Такой код недопустим, работать будет не стабильно, он не масштабируется и его поддержка невозможна. Ему здесь не место!

И ты, Брут. А он тебя жалел, говорил, флудерасты выгнали, на форум не пущают.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

DetSimen,точно херня с буфером на 30 вылезла.

/*cluster*/
template <typename T> inline Print & operator << (Print &s, T n) {
  s.print(n);
  return s;
}
#include <Wire.h>
#define SIZE_CLUSTER 32 // размер кластера
#define MAX_CLUSTER 128 // кол-во кластеров
class buffer_t {
  public:
    byte buffer[SIZE_CLUSTER];
    buffer_t();
    buffer_t(const __FlashStringHelper* txt);
};
buffer_t::buffer_t(void) {
  for (int i = 0; i < SIZE_CLUSTER; i++)buffer[i] = '!';
}
buffer_t::buffer_t(const __FlashStringHelper* txt) {
  int len = strlen_P((const char*)txt);
  if (len > SIZE_CLUSTER)len = SIZE_CLUSTER;
  for (int i = 0; i < SIZE_CLUSTER; i++)buffer[i] = pgm_read_byte_near((const char*)txt + i);
}
class e24c32 {
  protected:
    byte adr_i2c;
  public:
    byte buffer[SIZE_CLUSTER];
    byte cluster;
    void save_cluster();
    void load_cluster();
    void viev_byffer();
    void save_byffer(buffer_t obj);
    e24c32(byte adr): adr_i2c(adr) {}
    void init();
};
void e24c32::init() {
  Wire.begin();
}
void e24c32::save_cluster() {
  Wire.beginTransmission(adr_i2c);
  uint16_t address = cluster * SIZE_CLUSTER;
  Wire.write(address >> 8);
  Wire.write(address & 0xFF);
  for (byte i = 0; i < SIZE_CLUSTER; i++) Wire.write(buffer[i]);
  Wire.endTransmission();
  delay(10);
}
void e24c32::load_cluster() {
  Wire.beginTransmission(adr_i2c);
  uint16_t address = cluster * SIZE_CLUSTER;
  Wire.write(address >> 8);
  Wire.write(address & 0xFF);
  Wire.endTransmission();
  Wire.requestFrom(adr_i2c, (byte)SIZE_CLUSTER );
  for (byte i = 0; i < SIZE_CLUSTER; i++)
    if (Wire.available())
      buffer[i] = Wire.read();
}
void e24c32::viev_byffer() {
  for (int i = 0; i < SIZE_CLUSTER; i++) {
    char tmp = buffer[i];
    if (tmp == 0) break;
    Serial << tmp;
  }
  Serial << F("\n");
}
void e24c32::save_byffer(buffer_t obj = buffer_t()) {
  for (int i = 0; i < SIZE_CLUSTER; i++)buffer[i] = obj.buffer[i];
}
e24c32 cluster(/* адр i2c*/0x57);
void setup() {
  Serial.begin(9600);
  cluster.init();
  cluster.save_byffer();//<
  cluster.save_cluster();
  Serial << F("1\n");
  cluster.viev_byffer();
  cluster.save_byffer(F("qwertyuiop"));
  Serial << F("2\n");
  cluster.viev_byffer();
  cluster.load_cluster();
  Serial << F("3\n");
  cluster.viev_byffer();
}

void loop() {
}
/* Выведено
  1
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2
  qwertyuiop
  3
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Hб
*/

ПС: и да когда кому-нибудь захочется проверить этот код не забудьте подключить модуль

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Logik пишет:
там классов нет! И даже без шаблонов.
А уж про лямбды я вообще молчу!

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Примитив но просто не интересовался этим.

void setup() {
  Serial.begin(9600);
  String AAA(F("1234567890"));
  Serial.println(AAA.begin());
}
void loop() {

}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

qwone пишет:

Примитив но просто не интересовался этим.

void setup() {
  Serial.begin(9600);
  String AAA(F("1234567890"));
  Serial.println(AAA.begin());
}
void loop() {

}

и так тоже отрабатывает
 

void setup() {
  Serial.begin(9600);
  String AAA(("1234567890"));
  Serial.println(AAA.begin());
}
void loop() {

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ua6em пишет:
и так тоже отрабатывает
Но посмотрите на код #153  Мне пришлось городить class buffer_t , а мог бы обойтись String. Да и ваша версия отъедает ОЗУ.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

qwone пишет:

Да и ваша версия отъедает ОЗУ.

А Ваша? Точно так же отъёдает, ни на байт не меньше. Только не статикой, а запросом памяти при работе конструктора.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

/**/
#include <EEPROM.h>
void saveStringToEeprom(int adr, String obj);
void loadStringFromEeprom(int adr, String &obj);
void saveStringToEeprom(int adr, String obj) {
  unsigned int len = obj.length() + 1;
  for (unsigned int i = 0; i < len; i++) EEPROM.write(adr + i, obj[i]);
}
void loadStringFromEeprom(int adr, String &obj) {
  obj = "";
  uint8_t tmp;
  do {
    tmp = EEPROM.read(adr);
    adr++;
    obj += String((char)tmp);
  }
  while (tmp != 0);
}
//---------------------------------------------
const int adr1 =/*адресс eeprom*/10;
const int adr2 =/*адресс eeprom*/20;
//-----------------------------------------------------
void setup() {
  Serial.begin(9600);
  String aaa("qwerty");
  Serial.println(aaa);
  saveStringToEeprom(adr1, F("qwone"));
  saveStringToEeprom(adr2, F("Winnie the Pooh"));
  loadStringFromEeprom(adr1, aaa);
  Serial.println(aaa);
  loadStringFromEeprom(adr2, aaa);
  Serial.println(aaa);
}

void loop() {
}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Пух, ты лучше на выборы сходи. 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

DetSimen, вы тоже сходите. Напишите на бумажке свой выбор и бростьте ближайшую урну.Результат будет такой же.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Пух, за что так с памятью-то? Совсем не жалко? Чё она тебе плохого сделала, что ты её так?

#include <MemoryExplorer.h>

/**/
#include <EEPROM.h>
void saveStringToEeprom(int adr, String obj);
void loadStringFromEeprom(int adr, String &obj);
void saveStringToEeprom(int adr, String obj) {
  unsigned int len = obj.length() + 1;
  for (unsigned int i = 0; i < len; i++) EEPROM.write(adr + i, obj[i]);
}
void loadStringFromEeprom(int adr, String &obj) {
  unsigned int len = 0;
  while (EEPROM.read(adr + len) != 0) {
    len++;
  }
  char *buf = new char[len + 1];
  for (unsigned int i = 0; i <= len; i++) buf[i] = EEPROM.read(adr + i);
  obj = String(buf);
  delete[] buf;
}
//---------------------------------------------
const int adr1 =/*адресс eeprom*/10;
const int adr2 =/*адресс eeprom*/20;
//-----------------------------------------------------
void setup() {
	Serial.begin(115200);
	memoryReport("At Start");
	String aaa("qwerty");
	Serial.println(aaa);
	saveStringToEeprom(adr1, F("qwone"));
	saveStringToEeprom(adr2, F("Winnie the Pooh"));
	loadStringFromEeprom(adr1, aaa);
	Serial.println(aaa);
	loadStringFromEeprom(adr2, aaa);
	Serial.println(aaa);
	memoryReport("At End");
}

void loop() {
}

вот чего печатает

---- Memory report: At Start
HEAP:@025D(605)-@0832(2098);
Unallocated from:@025D(605);
Stack pointer: @08B2(2226)
Free List: EMPTY
-----
qwerty
qwone
Winnie the Pooh
---- Memory report: At End
HEAP:@025D(605)-@0832(2098);
Unallocated from:@028A(650);
Stack pointer: @08B2(2226)
Free List:
	Block at:@025D(605); Size:25
-----

Это тока фрагментация, а сколько там по ходу дела нафик не нужных запросов - жуть, сам посмотри.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/**/
void saveStringToEeprom(int adr, String obj) {
  unsigned int len = obj.length() + 1;
  for (unsigned int i = 0; i < len; i++, adr++)
    eeprom_write_byte((uint8_t*)adr, obj[i]);
}
void loadStringFromEeprom(int adr, String &obj) {
  obj = "";
  uint8_t tmp;
  do {
    tmp = eeprom_read_byte((uint8_t*)adr);
    adr++;
    obj += String((char)tmp);
  }
  while (tmp != 0);
}
String StringFromEeprom(int adr) {
  String obj("");
  uint8_t tmp;
  do {
    tmp = eeprom_read_byte((uint8_t*)adr);
    adr++;
    obj += String((char)tmp);
  }
  while (tmp != 0);
  return obj;
}
//---------------------------------------------
const int adr1 =/*адресс eeprom*/10;
const int adr2 =/*адресс eeprom*/20;
//-----------------------------------------------------
void setup() {
  Serial.begin(9600);
  String aaa("qwerty");
  Serial.println(aaa);
  saveStringToEeprom(adr1, F("qwone"));
  saveStringToEeprom(adr2, F("Winnie the Pooh"));
  
  loadStringFromEeprom(adr1, aaa);
  Serial.println(aaa);
  
  String bbb(StringFromEeprom(adr2));
  Serial.println(bbb);
}

void loop() {
}

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

qwone пишет:

/**/
void saveStringToEeprom(int adr, String obj) {
  unsigned int len = obj.length() + 1;
  for (unsigned int i = 0; i < len; i++, adr++)
    eeprom_write_byte((uint8_t*)adr, obj[i]);
}
void loadStringFromEeprom(int adr, String &obj) {
  obj = "";
  uint8_t tmp;
  do {
    tmp = eeprom_read_byte((uint8_t*)adr);
    adr++;
    obj += String((char)tmp);
  }
  while (tmp != 0);
}
String StringFromEeprom(int adr) {
  String obj("");
  uint8_t tmp;
  do {
    tmp = eeprom_read_byte((uint8_t*)adr);
    adr++;
    obj += String((char)tmp);
  }
  while (tmp != 0);
  return obj;
}
//---------------------------------------------
const int adr1 =/*адресс eeprom*/10;
const int adr2 =/*адресс eeprom*/20;
//-----------------------------------------------------
void setup() {
  Serial.begin(9600);
  String aaa("qwerty");
  Serial.println(aaa);
  saveStringToEeprom(adr1, F("qwone"));
  saveStringToEeprom(adr2, F("Winnie the Pooh"));
  
  loadStringFromEeprom(adr1, aaa);
  Serial.println(aaa);
  
  String bbb(StringFromEeprom(adr2));
  Serial.println(bbb);
}

void loop() {
}

 

Строка номер 2 - надо по ссылке передавать параметр типа String, чтобы не было копирования, со всеми вытекающими, типа жёсткой работы с памятью.

Писать/читаться строки в EEPROM лучше с префиксом - сколько байт сохранено. У String есть чудесный метод reserve, который избавит тебя от дичайшей переаллокации каждый раз, когда ты плюсуешь к строке один байт. Представь, что у тебя сохранена строка в 50 байт - в твоём случае это целых 50 выделений/освобождений памяти, зачем ты так не любишь микроконтроллеры?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

DIYMan пишет:

... У String есть чудесный метод ...

Вот если меня спросить, что мне более всего нравится в стрингах, то я отвечу, что в "стрингах" мне более всего нравятся барышни... лет 25ти. ;))))

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

wdrakula пишет:
барышни... лет 25ти. ;))))
Я бы сказал ОТ 25. До 25 у них много всякой романики в башке, а потом они на эти вещи ширше смотрят :)

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Ответ на #163.

Квон, я понимаю, что сказать нам - дуракам хоть слово, с высоты твое величия - западло. А потому я не знаю, зачем ты выложил этот вариант. Но, если в смысле, что в нём нету фрагемнтации памяти, то мимо - никуда она не делась, смотри

#include <MemoryExplorer.h>

/**/
void saveStringToEeprom(int adr, String obj) {
  unsigned int len = obj.length() + 1;
  for (unsigned int i = 0; i < len; i++, adr++)
    eeprom_write_byte((uint8_t*)adr, obj[i]);
}
void loadStringFromEeprom(int adr, String &obj) {
  obj = "";
  uint8_t tmp;
  do {
    tmp = eeprom_read_byte((uint8_t*)adr);
    adr++;
    obj += String((char)tmp);
  }
  while (tmp != 0);
}
String StringFromEeprom(int adr) {
  String obj("");
  uint8_t tmp;
  do {
    tmp = eeprom_read_byte((uint8_t*)adr);
    adr++;
    obj += String((char)tmp);
  }
  while (tmp != 0);
  return obj;
}
//---------------------------------------------
const int adr1 =/*адресс eeprom*/10;
const int adr2 =/*адресс eeprom*/20;
//-----------------------------------------------------
void setup() {
  Serial.begin(115200);
  memoryReport("At Start");
  String aaa("qwerty");
  Serial.println(aaa);
  saveStringToEeprom(adr1, F("qwone"));
  saveStringToEeprom(adr2, F("Winnie the Pooh"));

  loadStringFromEeprom(adr1, aaa);
  Serial.println(aaa);

  String bbb(StringFromEeprom(adr2));
  Serial.println(bbb);
  memoryReport("Freed p1");
}

void loop() {
}

Печатаить

---- Memory report: At Start
HEAP:@025F(607)-@082A(2090);
Unallocated from:@025F(607);
Stack pointer: @08AA(2218)
Free List: EMPTY
-----
qwerty
qwone
Winnie the Pooh
---- Memory report: Freed p1
HEAP:@025F(607)-@082A(2090);
Unallocated from:@0282(642);
Stack pointer: @08AA(2218)
Free List:
	Block at:@0268(616); Size:6
-----

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну и зарисовки по Морзе

/**/
//-------------------------------------------------
const byte st_none       = 0;
const byte st_next       = 1;
const byte st_dot        = 2;
const byte st_dush       = 3;
const byte st_pause_dot = 4;
const byte st_pause_dush = 5;
class cMorse {
  protected:
    String buffer;
    unsigned int ii;
    byte pin;
    unsigned long past;
    unsigned long time;
    unsigned long dot_time;
    byte state, next_state;
    void set( byte s);
  public:
    cMorse(byte p);
    void init(unsigned long t = 300);
    void run();
    void play(String msg);
};
void cMorse::set(byte s) {
  state = s;
  past = millis();
  while (state == st_next) {
    char tmp = buffer[ii++];
    switch (tmp) {
      case '.':
        state = st_dot;
        break;
      case '-':
        state = st_dush;
        break;
      case ' ':
        state = st_pause_dush;
        break;
      case '\0':
        state = st_none;
        break;
    }
  }
  switch (state) {
    case  st_none:
      Serial.print(F("OK"));
      break;
    case  st_next:
      break;
    case  st_dot:
      Serial.print(F("."));
      digitalWrite(pin, HIGH);
      time = dot_time;
      next_state = st_pause_dot;
      break;
    case st_dush:
      Serial.print(F("-"));
      digitalWrite(pin, HIGH);
      time = dot_time * 3;
      next_state = st_pause_dot;
      break;
    case st_pause_dot:
      digitalWrite(pin, LOW);
      time = dot_time;
      next_state = st_next;
      break;
    case st_pause_dush:
      Serial.print(F(" "));
      digitalWrite(pin, LOW);
      time = dot_time * 3;
      next_state = st_next;
      break;
  }
}
cMorse::cMorse(byte p)
  : pin(p) {}
void cMorse::init(unsigned long t) {
  dot_time = t;
  ii = 0;
  set(st_none);
  pinMode(pin, OUTPUT);
}
void cMorse::run() {
  if (state != st_none && millis() - past >= time) set(next_state);
}
void cMorse::play(String msg) {
    buffer = msg;
    ii = 0;
    set(st_next);
}

cMorse Morse(/*пин*/13);
//-----------  кнопка  ------------------------
typedef void (*pDo)();
class Cl_Btn {
  protected:
    byte pin;
    unsigned long past;
    bool state;
    void set(bool s) {
      past = millis();
      state = s;
      if (s == true)Do();
    }
  public:
    pDo Do = [] {};
    Cl_Btn(byte p): pin(p) {}
    void init() {
      pinMode(pin, INPUT_PULLUP);
      set(false);
    }
    void run() {
      if (millis() - past >= 100) {
        switch (state) {
          case false :
            if (!digitalRead(pin)) set(true);
            break;
          case true :
            if (digitalRead(pin)) set(false);
            break;
        }
      }
    }
};
Cl_Btn Btn(/*пин*/2);// кнопка
void setup() {
  Serial.begin(9600);
  Morse.init(100);//0.1 секунды длит точки
  Btn.init();
  Btn.Do = [] {
    Serial.println();
    Morse.play(F("... --- ... "));// сообщение SOS
  };
}

void loop() {
  Morse.run();
  Btn.run();
}

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Ну с точками и тире каждый может. А ты с буквами покажи :)

А почему для статусов какой нибудь enum, ну или #define не используешь ? Какая у тебя на сей счет религия ?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

brokly пишет:

Ну с точками т тире каждый может. А ты с буквами покажи :)

Да там всего лишь это еще раз обернуть. Передавать побуквенно заменив буквы на точки и все. Долго таблицу составлять для всех букв русских английских больших и маленьких и спец знаков.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Не, не экономно... Не красиво получится :(

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Квон - какой такой душ? 

st_dush

Тире - это dash.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

с точками, тире и генерацией частоты на пине самый простой скетч у Максима Клименко, занимает менее 1600 байт, озу 445 байт )))

// Arduino simply CW beacon
// (c) 2012 Max Klimenko
// emaster [at] mail.ru
// <a href="http://max-ter.livejournal.com/571.html" title="http://max-ter.livejournal.com/571.html" rel="nofollow">http://max-ter.livejournal.com/571.html</a>

// It sends beacon at 8 MHz from pin D9

// Beacon message
const char message[] = "VVV CQ CQ CQ DX DE BEACON BAND 40M 8000KHZ";

// Period of single point (ms)
const int point_time = 80;

// Carrier frequency divider.
// Carrier freq. (MHz) = 16 / (2 * (1 + freq_div))
const unsigned char freq_div = 1;

//////////////////////////////////////////////////////////////////
struct s_abc
{
        char letter;
        char sign[7];
};

const s_abc abc[] = {
        'A',".-", 'B',"-...", 'W',".--", 'G',"--.", 'D',"-..", 
        'E',".", 'V',"...-", 'Z',"--..", 'I',"..",
        'J',".---", 'K',"-.-", 'L',".-..", 'M',"--", 'N',"-.", 
        'O',"---", 'P',".--.", 'R',".-.", 'S',"...",
        'T',"-", 'U',"..-", 'F',"..-.", 'H',"....", 'C',"-.-.", 
        'Q',"--.-", 'Y',"-.--", 'X',"-..-", '1',".----",
        '2',"..---", '3',"...--", '4',"....-", '5',".....", 
        '6',"-....", '7',"--...", '8',"---..", '9',"----.",
        '0',"-----", '.',"......", ',',".-.-.-", ':',"---...", 
        ';',"-.-.-.", '(',"-.--.-", '`',".----.",
        '"',".-..-.", '-',"-....-", '/',"-..-.", '?',"..--..", 
        '!',"--..--", '@',".--.-.", '\\',"..-.-" };

unsigned char abc_size = sizeof(abc) / sizeof(abc[0]);

void setup()
{
  PORTB = 0;
  DDRB |= 1<<1;
  
  OCR1A = freq_div;
  TCCR1A = 0x48;
  TCCR1B = 0x09;
  
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);   // set the LED on
}

void send_letter(char l)
{
  if (l == ' ')
  {
    delay(point_time * 7);
    return;
  }
  
  unsigned char idx = 255;
  for (unsigned char i = 0; i < abc_size; i++)
    if (abc[i].letter == l)
    {
      idx = i;
      break;
    }
    
  if (idx == 255) return;
  
  const char *s = abc[idx].sign;
  
  for (unsigned char c = 0; s[c] != 0; c++)
  {
    char q = s[c];
    
    DDRB |= 1<<1;
    digitalWrite(13, HIGH);   // set the LED on
    
    if (q == '.') delay(point_time);
    else delay(point_time * 3);
    
    DDRB &= ~(1<<1);
    digitalWrite(13, LOW);   // set the LED off
    
    delay(point_time);
  }

  delay(point_time * 2);
}

void loop()
{
  for (int n = 0; message[n] != 0; n++)
    send_letter(message[n]);
  
  delay(2000);
}

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

ua6em пишет:

с точками, тире и генерацией частоты на пине самый простой скетч у Максима Клименко, занимает менее 1600 байт, озу 445 байт )))

Расход ОЗУ в приведённом скетче можно сократить раз в 10 ;) Переместив кое-чего во флеш ;)

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
const char CODE[] = {
  B0000000, B01110011, B0000000, B0000000, B0000000, B0000000, B0000000, B0000000,// !"# $%&'
  B0000000, B0000000, B0000000, B0000000, B01010101, B01010101, B0000000, B0110010,//()*+ -,./

  B0111111, B0101111, B0100111, B0100011, B0100001, B0100000, B0110000, B0111000,//0123 4567
  B0111100, B0111110, B0000000, B0000000, B0000000, B0000000, B0000000, B01001100,//89:; <=>?

  B01011010, B0101, B011000, B011010, B01100, B010, B010010, B01110,//@ABC DEFG
  B01000, B0100, B010111, B01101, B010100, B0111, B0110, B01111,//HIJK LMNO

  B010110, B011101, B01010, B01000, B011, B01001, B010001, B01011,//PQRS TUVW
  B011001, B011011, B011100, B0000000, B0000000, B0000000, B0000000, B0000000,//XYZ[ \]^_

  B0000000, B0101, B011000, B011010, B01100, B010, B010010, B01110,//`abc defg
  B01000, B0100, B010111, B01101, B010100, B0111, B0110, B01111,//hijk lmno

  B010110, B011101, B01010, B01000, B011, B01001, B010001, B01011,//pgrs tuvw
  B011001, B011011, B011100, B0000000, B0000000, B0000000, B0000000, B0000000 //xyz{ |}~
};
String msg(".,/?!@0123456789 abcdef");
void setup() {
  Serial.begin(9600);
  for (unsigned int i = 0; i < msg.length(); i++) {
    String aaa;
    byte tmp = CODE[msg[i] - ' '];
    if (tmp == 0) aaa = "  ";
    else {
      bool f = 0;
      aaa = "";
      for (int i = 0; i < 8; ++i) {
        if (f) {
          if (tmp & 0x80) aaa += "-";
          else aaa += ".";
        }
        else if (tmp & 0x80) f = 1;
        tmp = tmp << 1;
      }
    }
    Serial.println();
    Serial.print(msg[i]);
    Serial.print("   ");
    Serial.print(aaa);
  }
}

void loop() {

}

ua6em, я не стрелюсь к простым скетчам или компактным. Я стремлюсь к таким что бы и опыт подчерпнуть и потом в процессе совместить с другими компонентами, причем по возможности не блокирую их работу.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DIYMan пишет:

ua6em пишет:

с точками, тире и генерацией частоты на пине самый простой скетч у Максима Клименко, занимает менее 1600 байт, озу 445 байт )))

Расход ОЗУ в приведённом скетче можно сократить раз в 10 ;) Переместив кое-чего во флеш ;)

со строкой понятно, а массив как?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ua6em пишет:
со строкой понятно, а массив как?

Так же само. #250

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

ua6em пишет:

DIYMan пишет:

ua6em пишет:

с точками, тире и генерацией частоты на пине самый простой скетч у Максима Клименко, занимает менее 1600 байт, озу 445 байт )))

Расход ОЗУ в приведённом скетче можно сократить раз в 10 ;) Переместив кое-чего во флеш ;)

со строкой понятно, а массив как?

А чем массив отличается от строки таким, что его нельзя во флеш поместить? Правильно - ничем.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Пух, стандартное поведение древнего Виндовс АПИ, когда отдаваемый буфер может быть разного размера, это вызов функции с пустым указателем, тогда она реально ничо никуда не пишет, а отдает длину необходимого буфера.  После этого ты отгрызаешь памяти скока надо и вызываешь ф-ю повторно, уже с правильным указателем на буфер нужного размера, и отец Вындоуз его наполняет. 

Я сделал так (строка в ROM храница вместе с нулем) 

// читает строку из адреса ASrcAddr в буфер AStrBuf вместе с завершающим нулем
// отдает длину в байтах прочитанной строки (вместе с нулём)
// если вызвать с NULL вместо адреса буфера куда читать, можно невозбранно поиметь длину строки
// 
// Пример:
//
// size_t len = EEPROM.ReadString(0x100, NULL);	сначала узнаем, скока байт надо (вместе с нулём)
// char *str = new char[len];				потом выделим память
// EEPROM.ReadString(0x100, str);				потом прочитаем строку
// Serial << str << '\n';					чонить с ней сделаем
// delete[] str;						и удалим, када станет не надо

size_t ReadString(addr_t ASrcAddr, char *AStrBuf) {
	char c;
	size_t len = 0;
	do {
		c = readByte(ASrcAddr++);
		if (AStrBuf != NULL) AStrBuf[len] = c;
	} while (len++, (c > '\0'));

	return len;
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DIYMan пишет:

ua6em пишет:

DIYMan пишет:

ua6em пишет:

с точками, тире и генерацией частоты на пине самый простой скетч у Максима Клименко, занимает менее 1600 байт, озу 445 байт )))

Расход ОЗУ в приведённом скетче можно сократить раз в 10 ;) Переместив кое-чего во флеш ;)

со строкой понятно, а массив как?

А чем массив отличается от строки таким, что его нельзя во флеш поместить? Правильно - ничем.

у меня не получилось, компилируется но не работает )))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/**/
void saveToEeprom(int adr, String obj) {
  unsigned int len = obj.length() + 1;
  for (unsigned int i = 0; i < len; i++, adr++)
    eeprom_write_byte((uint8_t*)adr, obj[i]);
}
String loadFromEeprom(int adr) {
  unsigned int a = adr;
  for (; eeprom_read_byte((uint8_t*)a) != 0; a++);
  String obj;
  obj.reserve(a - adr + 1);
  uint8_t tmp;
  do {
    tmp = eeprom_read_byte((uint8_t*)adr++);
    obj += String((char)tmp);
  }
  while (tmp != 0);
  return obj;
}
//---------------------------------------------
const int adr1 =/*адресс eeprom*/10;
const int adr2 =/*адресс eeprom*/20;
//-----------------------------------------------------
void setup() {
  Serial.begin(9600);
  String aaa("qwerty");
  Serial.println(aaa);
  saveToEeprom(adr1, F("qwone"));
  saveToEeprom(adr2, F("Winnie the Pooh"));

  Serial.println(loadFromEeprom(adr1));
  Serial.println(loadFromEeprom(adr2));
}

void loop() {
}

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Ну вот, квон - осталось дооптимизировать, сохраняя байт длины строки перед самой строкой, и при чтении - вычитывать сначала один байт, потом резервировать память, потом - читать данные. Не помешает ещё заголовок в пару байт, чтобы убедиться, что данные таки сохранены.

По итогу что это всё даёт:

1. Есть заголовок - проверка записи на валидность;

2. Есть длина данных - не надо её высчитывать мееедленным чтением из EEPROM.

На примере строки в 1 байт длиной: твой вариант (с хранением нулевого завершающего байта) - даст чтений 2 + 2 = 4. Мой вариант, с заголовком из двух байт, байтом длины и данными, даст чтений 2 + 1 + 1 = 4. При этом мой вариант бьёт твой, начиная с длины строки > 1.

Напишешь ещё вариант? Думаю, пригодится ;) 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

DIYMan пишет:

мой вариант бьёт твой, начиная с длины строки > 1.

Пожалуй, я с тобой соглашуся.  Хоть чтение и не так тормозит, как запись, но сётаки переделаю. 

Logik
Онлайн
Зарегистрирован: 05.08.2014

Ой квон, безнадежен ты. Абсолютно безнадежен.

Твое:

void saveToEeprom(int adr, String obj) {
  unsigned int len = obj.length() + 1;
  for (unsigned int i = 0; i < len; i++, adr++)
    eeprom_write_byte((uint8_t*)adr, obj[i]);
}

String loadFromEeprom(int adr) {
  unsigned int a = adr;
  for (; eeprom_read_byte((uint8_t*)a) != 0; a++);
  String obj;
  obj.reserve(a - adr + 1);
  uint8_t tmp;
  do {
    tmp = eeprom_read_byte((uint8_t*)adr++);
    obj += String((char)tmp);
  }
  while (tmp != 0);
  return obj;
}

const int adr1 =/*адресс eeprom*/10;

void setup() {
  Serial.begin(9600);
  saveToEeprom(adr1, F("qwone"));
  Serial.println(loadFromEeprom(adr1));
}
void loop() {
}

Скетч использует 3200 байт (10%) памяти устройства. Всего доступно 30720 байт.

Правильное:

void saveToEeprom(int adr, const char * p) {
  uint8_t a;
  do
  {
    a= pgm_read_byte(p++);
    eeprom_write_byte((uint8_t*)adr++,a);
  } while (a);

}

String loadFromEeprom(int adr) {
  unsigned int a = adr;
  for (; eeprom_read_byte((uint8_t*)a) != 0; a++);
  String obj;
  obj.reserve(a - adr + 1);
  uint8_t tmp;
  do {
    tmp = eeprom_read_byte((uint8_t*)adr++);
    obj += String((char)tmp);
  }
  while (tmp != 0);
  return obj;
}

const int adr1 =/*адресс eeprom*/10;
const char Sub[] PROGMEM ="pustozvon";

void setup() {
  Serial.begin(9600);
  saveToEeprom(adr1, Sub);
  Serial.println(loadFromEeprom(adr1));
}
void loop() {
}
Скетч использует 3088 байт (10%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 198 байт 
 
Виш! 112 байт на ровном месте! И притом что "pustozvon" еще и длинней чем "qwone" ;)
Как избавится от стринга при переменной длине строки в loadFromEeprom, а заодно от использывания кучи и следовательно фрагментации - думай квон, думай ;) Меня ж тошнить начинает когда я вижу два прохода в loadFromEeprom и return obj.
 
 
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Мда.  В какую битву титанов я влес...  А ведь даже писАть не умею. :) 

Но я, кста, не уверен, что он тут хотел из EEPROMa в EEPROM писать

void saveToEeprom(int adr, const char * p) {
  uint8_t a;
  do
  {
    a= pgm_read_byte(p++);
    eeprom_write_byte((uint8_t*)adr++,a);
  } while (a);

}

мне кажеца, *p это указатель на ОЗУ. 

Logik
Онлайн
Зарегистрирован: 05.08.2014

кажется - проверь! Не сцо! В боях крепчают! Оба кода рабочие. А PROGMEM и EEPROM - точно разные штуковины.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

АААААА   там же из флэша в EEPROM, точно.  Звиняйте. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Logik пишет:

кажется - проверь! Не сцо! В боях крепчают! Оба кода рабочие. А PROGMEM и EEPROM - точно разные штуковины.

в WAVGAT это одно и тоже вроде как, только адреса разные

Logik
Онлайн
Зарегистрирован: 05.08.2014

Да. В WAVGAT по другому. Но не суть важно, важно другое - указатель (или адрес) всегда эффективней будет.

Еще один забавный пример, давно хотел глянуть на эти цифры.

void setup() {
  int t;
  // put your setup code here, to run once:
  Serial.begin(9600);

  for(char c='1';c<'z';c++)
  {
    t=micros();
    Serial.print(c);
    Serial.print(':');
    Serial.println((int)micros()-t);
  }
}

void loop() {
  // put your main code here, to run repeatedly:
}

Все просто, меряем время вывода в сириал. Имеем

1:12
2:16
3:16
4:12
5:12
6:16
7:16
8:12
9:16
::12
;:12
<:1728
=:2076
>:2076
?:2076
@:2076
 
На 2 порядка!!!
Все просто, пока в буфер помещается - быстро. Потом сильно медлено. 
На первый взгляд это к примерам выше вобще не относится. Но только на первый. Т.к. на второй позволяет понять есть ли разница между выводом всей строки сразу и выводом её по символьно. Ну и когда как стоит делать. Кстати 2076мксек - время на реальную, физическую отправку 2 байт на скорости 9600бод.
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Logik пишет:

 Кстати 2076мксек - время на реальную, физическую отправку 2 байт на скорости 9600бод.

так буфер у сериала вроде как должен быть 16 байт, куда остальные делись?

Logik
Онлайн
Зарегистрирован: 05.08.2014

Я слышал что 64байта по умолчанию. И по примеру тоже похоже. Первые 11 быстро прошли. Имеют строк  по 6 байт в строке. Итого 66.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ua6em пишет:

Logik пишет:

 Кстати 2076мксек - время на реальную, физическую отправку 2 байт на скорости 9600бод.

так буфер у сериала вроде как должен быть 16 байт, куда остальные делись?

изучи нимательно 

#if ((RAMEND - RAMSTART) < 1023)
#define SERIAL_TX_BUFFER_SIZE 16
#else
#define SERIAL_TX_BUFFER_SIZE 64
#endif

и доложи, у какой ATMeg-и Serial буфер 16 байт.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

ua6em пишет:

Logik пишет:

 Кстати 2076мксек - время на реальную, физическую отправку 2 байт на скорости 9600бод.

так буфер у сериала вроде как должен быть 16 байт, куда остальные делись?

изучи нимательно 

#if ((RAMEND - RAMSTART) < 1023)
#define SERIAL_TX_BUFFER_SIZE 16
#else
#define SERIAL_TX_BUFFER_SIZE 64
#endif

и доложи, у какой ATMeg-и Serial буфер 16 байт.

это тлетворное влияние PC-XT