Уменьшить размер скетча (кода) ARDUINO
- Войдите на сайт для отправки комментариев
Втр, 26/07/2016 - 22:59
Помогите пожалуйста уменьшить код.
#define PIN_out 2 // Выход на RF модуль (digital) #define Btn0000_Pin 3 // Вход, на котором кнопка (digital) #define DeviceFunction 0 // Поле DevFunc 16-битного пакета #define InWait_TimeOut 4 // seconds - время между пакетами, // когда от датчика нет срабатываний #define AccelerateTimes 40 // times of accelerated trasmission // (кол-во ускоренных передач пакетов, // когда датчик сработал) #define lvl_0 LOW boolean lvl_1 = !lvl_0; #define pilotPeriod 1200 #define HPeriod 500 #define LPeriod 2000 void setup() { DDRB |= (1<<PIN_out); DDRB &= ~(1<<Btn0000_Pin); } void sendPacket16(byte DevFunc, byte Data, byte pilotPeriods = 7); byte eventID = 0; byte transmissionID = 0; byte AccelerationCounter = 0; unsigned long LastTransmissionTC; void loop() { unsigned long TC = millis(); boolean SensorEvent = digitalRead(Btn0000_Pin); if(SensorEvent) { eventID++; AccelerationCounter = AccelerateTimes; } unsigned long tDW; unsigned long curTimeOut = 500 + ((unsigned long)InWait_TimeOut * 1000 - 500) * (tDW = AccelerateTimes - AccelerationCounter) / AccelerateTimes * tDW / AccelerateTimes; if(TC - LastTransmissionTC >= curTimeOut) { byte dataByte = transmissionID << 4 | eventID & 0x0F; transmissionID++; sendPacket16(DeviceFunction, dataByte, 7); if(AccelerationCounter) AccelerationCounter--; LastTransmissionTC = millis(); } } void sendPacket16(byte DevFunc, byte Data, byte pilotPeriods) { unsigned long pilotPeriod_half = pilotPeriod / 2; unsigned long HPeriod_half = HPeriod / 2; unsigned long LPeriod_half = LPeriod / 2; unsigned long lastChangeMicros; unsigned long m; word PacketData = (word)Data << 8; PacketData |= (DevFunc & 0x0F) << 3; byte even_parity = 0; byte count1 = bitRead(PacketData,3); byte b; for(byte i = 4; i < 16; i+=2) { even_parity ^= b = bitRead(PacketData,i); count1 += b; count1 += bitRead(PacketData, i+1); } PacketData |= count1 & 0x03; bitWrite(PacketData, 2, even_parity); digitalWrite(PIN_out, lvl_0); lastChangeMicros = micros(); for(byte i = 0; i < pilotPeriods; i++) { while((m = micros()) - lastChangeMicros < pilotPeriod_half) ; digitalWrite(PIN_out, lvl_1); lastChangeMicros = m; while((m = micros()) - lastChangeMicros < pilotPeriod_half) ; digitalWrite(PIN_out, lvl_0); lastChangeMicros = m; } for(byte n = 0; n < 16; n++) { boolean cur_bit = bitRead(PacketData,n); unsigned long cur_period_half = cur_bit ? HPeriod_half : LPeriod_half; while( (m = micros()) - lastChangeMicros < cur_period_half ); digitalWrite(PIN_out, lvl_1); lastChangeMicros = m; while( (m = micros()) - lastChangeMicros < cur_period_half ); digitalWrite(PIN_out, lvl_0); lastChangeMicros = m; } }
Спасибо!!!
Минимум на 160 байт
sendPacket16 вызывается один раз в цикле loop, т.ч. нет смысла выделять его в отдельную ф-цию. Но тут вероятно компилятор сообразит и м.б. уменьшения кода не последует, нужно проверять.
Возможно удастся сэкономить, если переписать millis() вручную на таймере. Обычно встроенные ф-ции сильно перегружены, а в библиотеках ардуино взаимодействие с таймерами реализовано из рук вон плохо.
Вместо деления можно использовать побитовый сдвиг, если позволяют требования к точности.
Тип long это оверхед для 8битного МК, "по возможности избегайте этого".
А кто нибуь сможет подсказать как это (digitalWrite(PIN_out, lvl_0);) Заменить на типо этого (PORTD |= (1 << PD1);PORTD &= ~ (1 << PD1); ) Впринципе если это все заменить, должно хватить места
Кстати да - вместо digitalRead\digitalWrite можно брать значения непосредственно из регистров. Port Registers
Вот их как раз и не пойму, записать низкий или высокий уровень, могу. А вот типо digitalWrite(PIN_out, lvl_0) тоесть сигнал lvl_0 не могу, точнее не знаю. Подскажите
Тольько так чтоли? или есть что то более изящное? Если так сделать, то остается минимум 104 байта убрать
Моя недолгая возня, но - надо проверять:
Собственно, поправленный код:
Заодно убрал варнинги, на которые ругался компилятор.
Спасибо. Но вопрос про регистры остался открытым (для личного познания)
Спасибо. Но вопрос про регистры остался открытым (для личного познания)
Посмотрите поправленный код, там как раз это и делается, просто вычисляется в setup номер бита и порта. То же самое можно прописать жёстко, если пин менять не надо - ещё подсократится код.
Не более изящно, но чуть более наглядно PORTD = (0<<PD2) или PORTD = PORTD & B11111011 для простоты PORTD &= B11111011
Ох чтот не пойму регистры в коде, можно эти регистры отдельно написать? Чтоб было более наглядно.
Ох чтот не пойму регистры в коде, можно эти регистры отдельно написать? Чтоб было более наглядно.
Вот тут - переменные, в которых всё, что надо:
Вот это - вычисление на основе переданного номера пина разных параметров - порт, битовая маска, регистр:
Вот это - запись в порт, сконфигурированный на выход, высокого или низкого уровня:
Вот это - чтение из порта, сконфигурированного на вход:
Если не надо менять пин в настройках - можно жёстко юзать нужные порты МК, суть от этого не поменяется, выше вам пример дали.
Теперь понял. Спасибо большое
Разве вот этот цикл:
не равнозначен:
Если это так, то переменные m и lastChangeMicros как бы и не нужны становяться. Или использование delay() сведет всю "экономию" на переменных и циклах к нулю?