Уменьшение размера кода C для ATmega8

Я в середине небольшого проекта с ATmega8. Я хотел бы считать температуру с датчика DS18B20, а затем отправить результаты с помощью передатчика rf433. Все хорошо, но размер моего исходника... У ATmega всего 7 168 байт памяти, а мой бинарник - 8 310 байт. Я удалил все ненужные вещи, и все равно это слишком много. Не могли бы вы помочь мне уменьшить размер? Я использую Arduino IDE для написания кода, может быть, на чистом C было бы легче?

Любая помощь приветствуется :)

Код:

// RF433
#include <VirtualWire.h>
// Dallas
#include <DallasTemperature.h>
#include <OneWire.h> 

//const char *message; // Our message to send
const int ONE_WIRE_BUS = 2; //DS18S20 Signal pin on digital 2

//Temperature chip i/o
OneWire oneWire(ONE_WIRE_BUS); // on digital pin 2

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature Sensors(&oneWire);

void setup() {
  // RF433
  vw_set_ptt_inverted(true);
  vw_setup(2000);

  Sensors.begin();
}

void loop() {
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  Sensors.requestTemperatures(); // Send the command to get temperatures

  float dTmp = Sensors.getTempCByIndex(0);
  // Why "byIndex"? 
  // You can have more than one IC on the same bus. 
  // 0 refers to the first IC on the wire

  char buf[6];
  dtostrf(dTmp, 6, 3, buf);

  char Msg[9];
  strcpy(Msg, "TP:");

  strncat(Msg, buf, 6);

  // Send temp.
  for (int i = 0; i < 10; ++i) // avoid loosing packets
  {
    vw_send((uint8_t *)Msg, strlen(Msg));
    vw_wait_tx();
    delay(300);
  }

  // Sleep 1 min.
  delay(60000);
}

person pablo7890    schedule 27.12.2014    source источник
comment
Вы используете системные функции, предоставляемые какой-то библиотекой. Откуда вы знаете, что размеры тех, сложенных, уже не больше, чем у вас есть?   -  person Jongware    schedule 27.12.2014
comment
Согласовано. Скиньте библиотеки. Или используйте более крупное устройство.   -  person Ignacio Vazquez-Abrams    schedule 27.12.2014
comment
Потому что такой код: // RF433 #include ‹VirtualWire.h› // Даллас #include ‹DallasTemperature.h› #include ‹OneWire.h› void setup() { } void loop() { } дает только 1506 байт. Так что это не их вина :(   -  person pablo7890    schedule 27.12.2014
comment
Этот тест неэффективен. Включение файлов заголовков недостаточно для компоновки библиотек; функции также должны быть действительно вызваны.   -  person Ignacio Vazquez-Abrams    schedule 27.12.2014
comment
Спасибо. Я сделал несколько тестов, и кажется, что function dtostrf(dTmp, 6, 3, buf); занимает около 1500 байт. Есть ли способ заменить это?   -  person pablo7890    schedule 27.12.2014
comment
Также в Интернете есть несколько доказательств того, что это возможно, как здесь, человек говорит, что его код подходит. Я не знаю, как он это сделал. Для меня его код больше 8400 байт... robertoinzerillo.com/wordpress/?p=74   -  person pablo7890    schedule 27.12.2014
comment
Наконец-то кто-то просит не преждевременную оптимизацию!   -  person Kevin    schedule 27.12.2014
comment
Вы пробовали флаги компилятора? -Os?   -  person Kevin    schedule 27.12.2014
comment
Его код едва подходил. И он, вероятно, использует более старые версии библиотек с меньшим количеством функций.   -  person Ignacio Vazquez-Abrams    schedule 27.12.2014
comment
Кевин, спасибо за ответ! Да, я только что попробовал этот флаг, как вы сказали, но ничего не произошло. Игнасио, спасибо! Я буду искать более старые библиотеки, потому что мне действительно не нужно все, что предлагается в новых версиях, но получение временных.   -  person pablo7890    schedule 27.12.2014
comment
Что ж, я попробовал эти старые библиотеки, и они больше не работают с моей версией IDE. Есть идеи по поводу основного вопроса?   -  person pablo7890    schedule 27.12.2014
comment
Если вы можете жить не с отправкой простого текста, а с упакованными двоичными представлениями ваших данных (т. е. с изменением протокола), вы можете отказаться от вызова dtostrf(). Даже без него несколько байтов и бесполезное копирование можно было бы сэкономить, используя char msg[9] = "TP:"; dtostrf(dTmp, 6, 3, msg + 3);. Кроме того, длина этой строки должна быть фиксированной или? Поэтому нет необходимости использовать strlen() на каждой итерации цикла впоследствии. Тем не менее, это действительно код C или, скорее, C++ или какая-то их производная? Я спрашиваю, потому что Sensors.getFoo() не похож на C, а если и выглядит, то содержит заменяемый указатель на функцию.   -  person Ulrich Eckhardt    schedule 27.12.2014
comment
Привет. Я попробовал char msg[9] = "TP:"; dtostrf(dTmp, 6, 3, msg + 3);, а двоичный файл всего на 7 байт легче, так что это мало помогает. Я не совсем понимаю, как отправлять упакованные двоичные представления данных? Язык Arduino основан на C и C++ со своими компонентами, хех ;) Спасибо   -  person pablo7890    schedule 27.12.2014
comment
Как сказал @UlrichEckhardt, вы должны стараться не использовать какие-либо строки во встроенном программном обеспечении. Работа со строками может быть очень тяжелой. Например, вы можете передавать только двоичные данные и форматировать их в виде строки в программном обеспечении для ПК.   -  person JF002    schedule 27.12.2014
comment
@up Спасибо, теперь я понял. Я сделал функцию: void sendData(float f) {byte * b = (byte *) &f; Serial.write(b[0]); Serial.write(b[1]); Serial.write(b[2]); Serial.write(b[3]);} но как теперь ее декодировать на Arduino-Receiver (ATMega328P, так что места много)?   -  person pablo7890    schedule 27.12.2014
comment
Просто прочитайте 4 байта в 32-битную переменную.   -  person Ignacio Vazquez-Abrams    schedule 29.12.2014
comment
@UlrichEckhardt: Arduino IDE — это g++ с пользовательским процессом сборки, который скрывает такие детали, как включение общих заголовков и связывание библиотек.   -  person Ignacio Vazquez-Abrams    schedule 31.12.2014


Ответы (1)


Спасибо всем вам, ребята. Вчера я нашел способ, как выполнить эту задачу. Может быть, кто-то будет искать ответ в будущем, так вот: я отказался от библиотеки Далласа, в конце концов оказалось, что она не нужна первой.

Программирование ATmega8 для работы с датчиком температуры DS18B20 и передатчиком RF433Mhz:

#include <OneWire.h> 
// RF433
#include <VirtualWire.h>

int DS18S20_Pin = 2; //DS18S20 Signal pin on digital 2

//Temperature chip i/o
OneWire ds(DS18S20_Pin); // on digital pin 2
int led = 13;
void setup(void) {
  // RF433
  vw_set_ptt_inverted(true);
  vw_setup(2000);

  pinMode(led, OUTPUT);
}

void loop(void) {
  float dTmp = getTemp();
  char buf[6];
  dtostrf(dTmp, 6, 3, buf);

  char Msg[10];
  strcpy(Msg, "TMP:");

  strncat(Msg, buf, 6);
  digitalWrite(led, HIGH);
  for (int i = 0; i < 10; ++i) // avoid loosing packets in the air
  {
    vw_send((uint8_t *)Msg, strlen(Msg));
    vw_wait_tx();
    delay(300);
  }
  digitalWrite(led, LOW);

  // Sleep 15 s.
  delay(15000);
}


float getTemp(){
  //returns the temperature from one DS18S20 in DEG Celsius

  byte data[12];
  byte addr[8];

  if ( !ds.search(addr)) {
    //no more sensors on chain, reset search
    ds.reset_search();
    return -1000;
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
    //   Serial.println("CRC is not valid!");
    return -1000;
  }

  if ( addr[0] != 0x10 && addr[0] != 0x28) {
    //   Serial.print("Device is not recognized");
    return -1000;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1); // start conversion, with parasite power on at the end

  byte present = ds.reset();
  ds.select(addr);  
  ds.write(0xBE); // Read Scratchpad


  for (int i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read();
  }

  ds.reset_search();

  byte MSB = data[1];
  byte LSB = data[0];

  float tempRead = ((MSB << 8) | LSB); //using two's compliment
  float TemperatureSum = tempRead / 16;

  return TemperatureSum;

}

Приведенный выше код в виде двоичного файла занимает около 6300 байт, так что остается еще немного места для некоторых улучшений.

Надеюсь, вы найдете его полезным :)

person pablo7890    schedule 29.12.2014