День добрый! Имеется arduino nano с подключенным к ней NRF24L01 и DHT11. Ардуина засыпает. При срабатывании прерывания - просыпается. Должно происходить чтений значений с dht, и записываться в массив данных. Во время пробуждения чтение с датчика может происходить несколько раз (2-4). Потом опять в сон. В тестовом варианте пробуждения раз в 40 секунд. В дальнейшем планируется раз в несколько минут. Проблема в том, что зачастую при первом обращении к dht, он выдает первое значение как бы из прошлого пробуждения. Например, первый запуск, все ок, считались значения. Во время сна - активно дышу на датчик, поднимается влажность, температура. Ардуина просыпается пишет первое значение, допустим, 36.00 29.00, а дальше 65.00 30.00 75.00 30.00 59.00 30.00 Т.е. значение отличается в два раза, оно явно не текущее. Вопрос в том, как быть и что делать? Какие есть идеи? Спойлер: Код тут Код (C++): #include <SPI.h> #include "nRF24L01.h" #include "RF24.h" #include "printf.h" #include "DHT.h" #include <avr/sleep.h> #define DHTPIN 5 // Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 9 & 10 RF24 radio(9, 10); // Topology uint64_t address = 0x1230123012; volatile float sendingData[] = {0,0}; enum STATE {state_sleep = 0, state_interrupt,state_wait}; uint8_t currentState = state_sleep; uint64_t t1 = 0; DHT dht(DHTPIN, DHT11); //Connect DHT void setup() { Serial.begin(9600); dht.begin(); delay(5000); printf_begin(); Serial.println("ROLE: RESPONSER"); // Setup and configure radio radio.begin(); radio.setAutoAck(1); // Ensure autoACK is enabled radio.enableAckPayload(); // Allow optional ack payloads radio.maskIRQ(1, 1, 0); radio.setPALevel(RF24_PA_LOW); radio.setRetries(0, 15); // Smallest time between retries, max no. of retries radio.setDataRate(RF24_2MBPS); radio.openReadingPipe(1, address); radio.startListening(); attachInterrupt(0, interruptGo,FALLING); //0 for pin 2, 1 for pin 3 delay(500); goSleep(); } void loop() { switch(currentState) { case state_interrupt: { delay(1000); sendingData[0] = dht.readHumidity(); delay(1000); sendingData[1] = dht.readTemperature(); delay(1000); readDataSendResponse(); currentState = state_wait; t1 = millis(); break; } case state_wait: { if(millis() - t1 > 10000) { currentState = state_sleep; } else { delay(500); } break; } case state_sleep: { goSleep(); } } } void goSleep() { delay(1000); set_sleep_mode(SLEEP_MODE_PWR_DOWN); cli(); sleep_enable(); sleep_bod_disable(); sei(); sleep_cpu(); sleep_disable(); } void interruptGo() { currentState = state_interrupt; } void readDataSendResponse() { byte pipeNo = 1; float gotData; Serial.print(" Set AckPayload: "); printSendingData(sendingData, sizeof(sendingData) / sizeof(sendingData[0])); Serial.println(); radio.writeAckPayload(pipeNo, sendingData, sizeof(sendingData) ); // This can be commented out to send empty payloads. while (radio.available(&pipeNo)) { radio.read(&gotData, sizeof(gotData)); } } void printSendingData(float *sendingData, size_t len) { for (int i = 0; i < len; i++) { Serial.print(sendingData[i]); Serial.print(" "); } } delay вставлял везде от безысходности... С радостью выслушаю критику по коду, пожелания и предложения.
Код нормальный, на delay от безысходности - не обращаем внимания По поводу проблемы - а что мешает отбрасывать первые пару измерений после пробуждения? Или применить фильтр, отбрасывающий из массива измерений крайние значения и берущий медиану? Или какой другой фильтр, типа арифметического среднего? Правильный ответ - ничего не мешает
Помог такой код: Код (C++): case state_interrupt: { for(int i =0;i< 10;i++) { dht.readHumidity(); dht.readTemperature(); delay(100); } //.... Без delay внутри цикла не работает.