Каким образом можно уменьшить размер скетча? Спойлер: спойлер Код (C++): #include <OneWire.h> #define led_max 5 #define led_min 3 #define ds18_b20 4 #define tranzistor 1 #define battery 2 #define out_chip 0 OneWire ds(ds18_b20); uint8_t start = 1; //1-заряжается, 0-разряжется volatile long ttime = 0; void led_off(void) { PORTB &= ~((1 << led_max) | (1 << led_min)); // выключвкм диоды } void blin_k(uint8_t pin) { led_off(); delay(1000);//ждем PORTB |= (1 << pin); delay(1000);//ждем } void B_blink(uint8_t pin) { led_off(); delay(200);//ждем PORTB |= (1 << pin); //включам delay(1000);//ждем } uint16_t analog_Read(void) { ADCSRA |= 1 << ADSC; //запуск преобразования ацп while (!(ADCSRA & (1 << ADIF))); //ждем окончания преобразования ADCSRA |= 1 << ADIF; //сбрасывание флага (ADLAR=0) byte low = ADCL;//чтение из регистров результата byte high = ADCH; // ADCSRA &= ~(1 << ADEN); // отключаем АЦП, для уменьшения энергопотребления return (high << 8) | low;// перобразуем } ISR(TIMER0_OVF_vect)//прерывание по переполнению { if (start == 1) { ttime++; } } void setup() { //----устанавливаем входы-выходы 0-вход, 1-выход DDRB = 0x3A;//0-вход от схемы , 1-транзистор, 2-батарея, 3-диод низкий уровень, 4-18b20, 5-диодвысокий уровень PORTB = 0; //устанавливаем логические уровни в 0 //------настройка Таймера0--------- TCCR0A = 0; TCCR0B = 0b00000101; //делитель 1024 TCNT0 = 0; TIMSK0 = 0b00000010; // Разрешение прерываний по переполнению //---------настройка АЦП ADMUX = battery; // выбор входного канала ADCSRA |= 1 << ADEN; //разрешение работы ацп sei(); } void loop() { noInterrupts();//запрещаем прерывания //-------работа с датчиком температуры uint8_t data[2]; ds.reset(); ds.write(0xcc); ds.write(0x44); delay(70);// точность 0,5 записана в EEPROMе ds.reset(); ds.write(0xcc); ds.write(0xBE); data[0] = ds.read(); data[1] = ds.read(); uint16_t tempr = ((data[1] << 8) | data[0]) >> 4; //-----конец вычислений uint16_t vol = analog_Read();//читаем значение аккумулятора interrupts();//разрешаем прерывани if (ttime == 164000) { // прошло 10 часов, и зарядка не закончилась ttime = 0; PORTB &= ~(1 << tranzistor);//отключаем транзистор зпрядки PORTB |= (1 << led_max) | (1 << led_min); //включам все диоды start = 10; } if (tempr > 40) {//если температура больше 40 PORTB &= ~(1 << tranzistor);//отключаем транзистор зпрядки start = 11; } else if (tempr < 21 && start == 11) {// когда температура упала до 20 PORTB |= 1 << tranzistor;//включаем транзистор зпрядки start = 1; } if (start == 1 && (PINB >> out_chip) & 0x01 == 0) {//идет зарядка. ждем пока батарейка зарядится до максимального уровня PORTB &= ~(1 << tranzistor);//отключаем транзистор зпрядки start = 0; //теперь будет процесс разрядки ttime = 0; } else if ( vol <= 540 && start == 0) { // ждем, когда на аккумуляторе меньше 3,4 PORTB |= (1 << tranzistor);// вкл транзистор зарядки start = 1;//запускаем процесс зарядки } //---------Аварийные ситуации----------- if (vol > 1000 && start < 11) { //если аккумулятор был вынут либо он выщел из строя PORTB &= ~(1 << tranzistor);//отключаем транзистор зпрядки start = 10; //неиспраность, напряжение превысло порог B_blink(led_max); } else if (vol < 100 && start < 11) { // слишком низкое напряжение, либо короткое замыкание PORTB &= ~(1 << tranzistor);//отключаем транзистор зпрядки start = 10; //неиспраность, напряжение превысло порог B_blink(led_min); } //---------------отображение уровня текущей зарядки------------- else if (start <= 1) { if (vol > 600 ) { //аккумулятор выше 4,2В led_off(); PORTB |= (1 << led_max);//включем высокой зарядки if (start == 1) {//если идет зарядка, мигаем светодиодом//60 blin_k(led_max);// функция мигания светодиодомм } } else if (vol < 550) { //если меньше 3,6в , вкл диод низной зарядки led_off(); PORTB |= (1 << led_min); if (start == 1) {//если идет зарядка, мигаем светодиодом blin_k(led_min);// функция мигания светодиодомм } } } //-------------------------------------------------------------------- } Attiny13a, ядро https://raw.githubusercontent.com/sleemanj/optiboot/master/dists/package_gogo_diy_attiny_index.json
Сначала неплохо бы глянуть результат работы компилятора и найти хотя бы одно место, где руками получится переписать оптимальнее.
1. Учитывая, что ты используешь только одну библиотеку - надо подумать об чистом С 2. Мигалки вынеси на прерывание таймера - вырежется delay. 3. return (high << 8) | low; -- реально цыкличесткого сдвига у него нет поэтому двигай в другую сторону 4. PORTB &= ~((1 << led_max) | (1 << led_min)); -- Как не парадоксально, но две отдельные команды сгенерируют более оптимальный код. 5. else if -- Если предыдущий IF имеет исключающее условие то такая конструкция не нужна Сколько сэкономить надо? На сколько я могу судить, ТВОЙ код весит не много. Большая часть ядро arduino
Это зарядное для литиевого аккумулятора. Заряжает - ждет пока разрядится- опять заряжает. Будет стоять в гараже на сигналке. Еще планирую прицепить нагреватель, чтоб холод не уробил аккумулятор, вместо одного светодиода. Скетч использует 946 байт (92%) памяти устройства. Всего доступно 1024 байт. Глобальные переменные используют 20 байт (31%) динамической памяти, оставляя 44 байт для локальных переменных. Максимум: 64 байт. 4 пункт сэкономил 2 байта. Завязать мигалки от прерывания была такая мысль, но слабо думал об этом и так и осталось.
Здесь все просто. Прерывание таймера ты уже сделал -я так понял 4 срабатывания в секунду. Мигалка имеет два параметра: - Длительность цикла (частота) - Длительность горения (скважность) Соответственно делаешь счетчик от 0 до "длительность цикла" - все задается в тиках таймера Соответственно два условия: при "счетчик = 0" ставиш HIGH при "счетчик=длительность горения" ставишь LOW В основном цикле меняешь эти два параметра и сбрасываешь счетчик в 0 На "С" delay() функция inline т.е. при ее вызове вставляется не код вызова функция а вся функция целиком. Поэтому фактически у тебя в коде 4 реализации delay(). Правда для Arduino IDE это надо бы проверить.
А в чем тут оптимизация? Имхо одно только неудобство от невозможности использовать более богатый синтаксис. В правой части только константы, выражение от них вычисляется на этапе компиляции. Итого должна получиться одна команда с постоянным аргументом.
Вопрос был - экономия места. ООП подразумевает удобство, но за это расплачивается понижением производительности и расход памяти. А в указанном примере от C++ очень мало. Особенности компилятора: Если устанавливает один бит то используется всего одна команда ассемблера Код (Text): SBI port, bit Если устанавливаются несколько битов, то это эквивалентно всему байту Код (Text): in reg, port andi reg, const out port, reg Соответственно небольшая экономия. В масштабах одно килобайта заметно. Дополнительно, не понадобится освобождать регистр.
Ну это сильно зависит от используемых фич, в плюсах из вкусного не только ООП есть и не любое использование ООП порождает дополнительные расходы. Ну так то да, я на первый вариант не рассчитывал. Кстати, если важна одновременность установки битов, то оптимизация с несколькими командами sbi не подойдет.
OneWire много весит. В ней одна только таблица CRC чего стоит... С аналоговым датчиком температуры можно много сэкономить. Точность большая не нужна как я понимаю. Даже диод в качестве датчика сойдет.
Добрый день. Есть несколько подобных функций: Код (C++): char buff[20]; for (byte i = 1; i <= 9; i ++){ switch (i) { case 1: sprintf(buff, "[V,%d,%d]", i, EE.u_show_data + 1); break; case 2: sprintf(buff, "[V,%d,%d]", i, EE.u_wiegand + 1); break; case 3: sprintf(buff, "[V,%d,%d]", i, EE.u_port_in[0] + 1); break; case 4: sprintf(buff, "[V,%d,%d]", i, EE.u_port_in[1] + 1); break; case 5: sprintf(buff, "[V,%d,%d]", i, EE.u_port_out[0] + 1); break; case 6: sprintf(buff, "[V,%d,%d]", i, EE.u_port_out[1] + 1); break; case 7: sprintf(buff, "[V,%d,%d]", i, EE.u_port_out[2] + 1); break; case 8: sprintf(buff, "[V,%d,%d]", i, EE.u_port_out[3] + 1); break; case 9: sprintf(buff, "[V,%d,%d]", i, EE.u_voice_hint + 1); break; } Serial.println(buff); } Возможна ли оптимизация данного куска с целью экономии места во flash ? Может есть более оптимизированный аналог sprintf ?
Разумеется, 100500 способами. Например, напишите вот так, думаю кило - кило триста как с куста: Код (C++): char buff[20] = "[V,"; const int arr[9] = { EE.u_show_data + 1, EE.u_wiegand + 1, EE.u_port_in[0] + 1, EE.u_port_in[1] + 1, EE.u_port_out[0] + 1, EE.u_port_out[1] + 1, EE.u_port_out[2] + 1, EE.u_port_out[3] + 1, EE.u_voice_hint + 1 }; for (byte i = 1; i <= 9; i++) { itoa(i, buff + 3, 10); uint8_t index = strlen(buff); buff[index] = ','; itoa(arr[i-1], buff + index + 1, 10); Serial.println(strcat(buff, "]")); }