💬 Various bootloader files based on Optiboot 6.2
-
@Samuel235
If you are using a nano, what crystal is mounted on it ? Fast flashing indicates the processor is running faster then the expected 8MHz (expected by the timing routines of the bootloader). Could it be a 16MHz model ?
In that case you could try to upload a sketch at a higher speed: 76K8 baud.
Or you can try to load the bootloader for 16MHz/D13 (which in effect is the standard bootloader of an Arduino).@GertSanders Soon as i say the fast flashing I instantly thought that its running quicker than needed, but i had no idea about the resetting that you have pointed out, so thanks for pointing that one out. The reason i didn't even bother trying the 16MHz settings in fuses would be that because when i read the fuses of the arduino before i did anything, it indicated that it was running with fuses of 8MHz and the blink sketch was perfectly timed on those settings.... Could it be a miss read on the fuse settings maybe? Should i read at a slower speed when using avrdude?
The crystal is so small on the nano and i can't even see the engraving with a microscope properly either.
I can confirm that the 16MHz bootloader is working perfectly on this nano. Thanks.
-
I have been running your bootloader for all my nodes now and that works very well.
But there is something that surprised me. When I compile the next sketch and compare that with the Moteino bootloader it's substantially larger./*************************************************************************************** ** ** Outdoor sensor v1.0 Measuring temperature, humdity, pressure and light level ** Calculating a weather forecast with the height comensated air pressure. ** powered by a solar panel and a 1000mAh Li-Ion battery. ** ** Scraped together by D Hille. MySensors library by Henrik Ekblad et al. ** ** Heat index calculation from DHT library by Adafruit ** MAX44009 bij Rob Tillaart ** Weather forecast based on AN3914 by Freescale ** ****************************************************************************************/ // MySensors definitions //#define MY_DEBUG // Enable debug prints (6 kb flash space) //#define MY_DEBUG_VERBOSE_SIGNING // Comment out when no signing is used or when everything is OK (3 kb flash space) #define MY_BAUD_RATE 57600 // Set serial baudrate #define MY_RADIO_RFM69 // Enable and select radio type attached //#define MY_IS_RFM69HW // Comment out when using standard RFM69W #define MY_NODE_ID 110 // Delete to use automatic ID assignment //#define MY_CORE_ONLY /**************************************************************************/ // Transport /**************************************************************************/ //#define MY_TRANSPORT_WAIT_READY_MS 1000 //Start the node even if no connection to the GW could be made (disable for sensor nodes). #define MY_TRANSPORT_STATE_RETRIES 1 #define MY_TRANSPORT_MAX_TSM_FAILURES (2u) #define MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE (60*1000ul) /**************************************************************************/ // Security /**************************************************************************/ //#define MY_SIGNING_ATSHA204 //#define MY_SIGNING_SOFT //#define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 //#define MY_SIGNING_REQUEST_SIGNATURES //#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = 0,.serial = {0xD0,0xB1,0x90,0x99,0xC3,0x03,0x08,0xD1,0x34}}} //#define MY_RFM69_ENABLE_ENCRYPTION /**************************************************************************/ // Sensor definitions /**************************************************************************/ #define BATTERY_POWERED #define battUpdater 300 //Number of TX actions to count before a new battery status update is sent. #define MY_DEFAULT_TX_LED_PIN 5 // Comment out when no LED is attached. #define MY_WITH_LEDS_BLINKING_INVERSE #define SENSOR_TYPE 3 // Sensor types: // 0.: no climate sensor attached // 1.: RFM69 on-die Temperature sensor on the RFM69 module (whole integers only) // 2.: DS18B20 Dallas one-wire sensor(data pin D14) // 3.: HTU21D Temp/humidity (I2C) // 4.: BME280 Temp/humidity/pressure (I2C) (node will wake every minute to keep up with trend measureing) #define SENSOR_UPDATE 2 // Time in minutes the sensor sends an update //#define LIGHT_SENSOR_PRESENT // Comment out when not present. (I2C) (Light sensor will update every 60 seconds.) //#define INTERRUPT_SENSOR_PRESENT // Comment out when not present (e. g. motion sensor connect to D3) #define alti 57 //altitude offset to compensate the barometric pressure /**************************************************************************/ // Debug definitions /**************************************************************************/ //#define LOCAL_DEBUG //Comment out to switch all debug messages off (saves 2 kb flash) #ifdef MY_DEBUG //Differentiate between global debug including radio and local debug #define LOCAL_DEBUG //for the sketch alone. #endif #ifdef LOCAL_DEBUG #define Sprint(a) (Serial.print(a)) // Macro as substitute for serial debug. Will be an empty macro when #define Sprintln(a) (Serial.println(a)) // debug is switched off #else #define Sprint(a) #define Sprintln(a) #endif /**************************************************************************/ #include <Button.h> #include <SPI.h> #include <Wire.h> #include <MySensors.h> //#include <SparkFunBME280.h> //#include <MAX44009.h> // Uncomment library used in sketch #include <Adafruit_HTU21DF.h> //#include <OneWire.h> //#include <DallasTemperature.h> #include <Vcc.h> #define BMEaddr 0x76 #define Max44099Addr 0x4A #define sketchName "sensorNode(living)" #define sketchVer "1.0" #define sensorPowerPin 20 #define digitalSensorPin 14 #define analogSensorPin A0 #define oneWireBusPin 14 #define interruptPin 3 #define altSensorPin 18 #define altAnalogPin A4 #define sensorPowerPin 6 #define chanTemp 0 #define chanHum 1 #define chanHeat 2 #define chanBaro 3 #define chanDelta 4 #define chanLight 5 #define chanRate 6 #define chanInterrupt 8 #define PULLUP false #define INVERT false #define bounceTime 20 #define sleepWait 500 //Time to wait in ms before node sleeps (to be able to receive notification messages). bool battPower = true; unsigned long currTime = 0; unsigned long sleepTime = (60000 * SENSOR_UPDATE); unsigned long lastSensorUpdate; unsigned long nextSensor; unsigned long measureTime; int wakeReason = -1; int sendLoop = 0; bool updated = false; bool ACKed = false; int sensorFunc = 0; float sensorData = 0.0; float heatTemp = 0.0; float heatHum = 0.0; bool interruptState = false; bool lastInterrupt = false; bool sensorPresent = false; bool lightPresent = false; bool interruptPresent = false; int minuteCount = 0; bool firstRound = true; float pressureAvg; // average value is used in forecast algorithm. float pressureAvg2; // average after 2 hours is used as reference value for the next iteration. float dP_dt; const int LAST_SAMPLES_COUNT = 5; float lastPressureSamples[LAST_SAMPLES_COUNT]; bool startUp = true; bool metric = true; int battStatCounter = 0; const float VccMin = 1.8; // Minimum expected Vcc level, in Volts. const float VccMax = 3.0; // Maximum expected Vcc level, in Volts. const float VccCorrection = 1.0/1.0; // Measured Vcc by multimeter divided by reported Vcc /**************************************************************************/ // Library declarations /**************************************************************************/ // Uncomment necessary declarations. //RFM69 wireless; //OneWire OWB(oneWireBusPin); //DallasTemperature DS18(&OWB); //DeviceAddress DS18address; Adafruit_HTU21DF HTU = Adafruit_HTU21DF(); //BME280 BME; //Max44009 lightMax(Max44099Addr); //Button reedContact(interruptPin, PULLUP, INVERT, bounceTime); MyMessage msgHum(chanHum, V_HUM); MyMessage msgTemp(chanTemp, V_TEMP); //MyMessage msgBaro(chanBaro, V_PRESSURE); //MyMessage msgTrend(chanUniversal, V_VAR5); //MyMessage msgLight(chanLight, V_LEVEL); //MyMessage msgIntr(chanInterrupt, V_TRIPPED); Vcc vcc(VccCorrection); /**************************************************************************/ // Error messages /**************************************************************************/ #if (defined INTERRUPT_SENSOR_PRESENT && defined LIGHT_SENSOR_PRESENT && SENSOR_TYPE >= 4) #error Motion sensor can anly be combined with either I2C OR one-wire sensors, not both. #endif #if (defined INTERRUPT_SENSOR_PRESENT && (defined LIGHT_SENSOR_PRESENT || SENSOR_TYPE == 4) && defined BATTERY_POWERED) #error Interrupt sensor is not compatible with trend sensors like 'baro' and 'light' because the timer will misalign. #endif #if (SENSOR_TYPE > 4) #error Not a valid sensor type! #endif /**************************************************************************/ void before(void) { Serial.println("\nReading config..."); #ifndef BATTERY_POWERED battPower = false; #endif sensorFunc = SENSOR_TYPE; #ifdef LIGHT_SENSOR_PRESENT lightPresent = true; #endif #ifdef INTERRUPT_SENSOR_PRESENT interruptPresent = true; lastInterrupt = reedContact.read(); #endif #if (defined MY_SIGNING_SOFT || defined MY_SIGNING_ATSHA204) #define sendPause 100 #else #define sendPause 50 #endif } /**************************************************************************/ void setup(void) { pinMode(sensorPowerPin, OUTPUT); //switch on the sensor power digitalWrite(sensorPowerPin, HIGH); wait(50); //wait 50 ms for the sensors to settle. switch (sensorFunc) { case 0: break; case 1: sensorPresent = true; break; case 2: //DS18.begin(); //DS18.getAddress(DS18address, 0); //DS18.setResolution(DS18address, 10); sensorPresent = true; break; case 3: HTU.begin(); sensorPresent = true; break; case 4: //startBME(); sleepTime = 60000; sensorPresent = true; break; } #if (lightPresent) sleepTime = 60000; sensorPresent = true; #endif #ifdef MY_DEBUG //Differentiate between global debug including radio and local debug sleepTime = 30000; //for the sketch alone. #endif batteryStats(); Serial.println("\nDone. \n\nStarting program.\n"); currTime = millis(); } /**************************************************************************/ void presentation() { Serial.println("Start radio and sensors"); sendSketchInfo(sketchName, sketchVer); Sprint("\nPresent "); if (sensorFunc >= 1) { wait(sendPause); present(chanTemp, S_TEMP, "Climate", true); Sprint("temperature"); } if (sensorFunc >= 3) { wait(sendPause); present(chanHum, S_HUM); Sprint(", humidity"); //wait(sendPause); //present(chanHeat ,S_TEMP); //Sprint(", heatindex"); } if (sensorFunc == 4) { wait(sendPause); present(chanBaro, S_BARO); Sprint(", barometric"); wait(sendPause); present(chanDelta, S_CUSTOM); Sprint(" and rate"); } Sprintln(" sensor."); if (lightPresent) { wait(sendPause); present(chanLight, S_LIGHT_LEVEL, "Light", true); Sprintln("\nLightsensor "); if (sensorFunc < 4) { wait(sendPause); present(chanRate, S_CUSTOM); Sprintln("with rate "); } Sprintln("presented."); } if (interruptPresent) { wait(sendPause); present(chanInterrupt, S_MOTION, "Motion", true); Sprintln("Interrupt sensor presented."); } wait(sendPause); } /**************************************************************************/ void loop(void) { if (wakeReason < 0) { Serial.println("Reading sensors..."); switch (sensorFunc) { case 0: break; case 1: updateRFM(); break; case 2: updateDS18(); break; case 3: updateHTU(); break; case 4: if (sendLoop <= 0) { updateBME(); updated = true; } else { Sprint("\nTrend: "); updateTrend(); sendLoop--; } break; } if (lightPresent) { updateMAX(); if (sensorFunc <= 3) { Sprint("\nTrend: "); updateTrend(); } } wakeReason = 0; Sprintln("\nSensors updated..."); } else if (wakeReason == 1) { updateInterrupt(); wakeReason = 0; } if (battStatCounter >= battUpdater) { batteryStats(); } if (updated) { sendLoop = SENSOR_UPDATE; updated = false; } if (millis() >= currTime + sleepWait) { startUp = false; sleepSensor(); } } /**************************************************************************/ void updateInterrupt() {/* Sprintln("\nInterrupt: "); interruptState = reedContact.read(); wait(50); if (interruptState == !lastInterrupt) { send(msgIntr.setSensor(chanInterrupt).set(interruptState),true); lastInterrupt = interruptState; } Sprint("Door/window is "); if (interruptState) { Sprintln("opened."); } else { Sprintln("closed"); }*/ } /**************************************************************************/ void updateRFM() {/* Sprintln("\nRFM: "); sensorData = wireless.readTemperature(); wait(20); send(msgTemp.set(sensorData, 0)); Sprint("Temperature: \t"); Sprint(sensorData); Sprintln(" sent."); battStatCounter++;*/ } /**************************************************************************/ void updateDS18() {/* Sprintln("\nOne-wire: "); DS18.requestTemperatures(); sensorData = DS18.getTempCByIndex(0); wait(20); send(msgTemp.set(sensorData, 2)); battStatCounter++; Sprint("Temperature: "); Sprint(sensorData); Sprintln(" sent.");*/ } /**************************************************************************/ void updateHTU() { Sprintln("\nHTU: "); sensorData = HTU.readTemperature(); heatTemp = sensorData; wait(20); send(msgTemp.set(sensorData, 1)); Sprint("Temperature: \t"); Sprint(sensorData); Sprintln(" sent."); sensorData = HTU.readHumidity(); heatHum = sensorData; wait(sendPause); send(msgHum.set(sensorData, 1)); Sprint("Humidity: \t"); Sprint(sensorData); Sprintln(" sent."); //wait(sendPause); //send(msgHeat.set(computeHeatIndex(heatTemp, heatHum), 1)); //Sprint("Heatindex sent."); battStatCounter++; } /**************************************************************************/ void updateBME() { /*Sprintln("\nBME: "); BME.begin(); wait(100); sensorData = (BME.readFloatPressure()/pow(1-(alti/44330.0),5.255)/100); if (!startUp) { trend(sensorData); send(msgBaro.set(sensorData,1)); Sprint("Pressure: \t"); Sprint(sensorData); Sprintln(" sent."); } if (!(minuteCount < 35 && firstRound)) { wait(sendPause); send(msgTrend.set(dP_dt,2)); Sprint("Trend: \t\t"); Sprint(dP_dt); Sprintln(" sent."); } wait(sendPause); sensorData = BME.readTempC(); heatTemp = sensorData; send(msgTemp.set(sensorData,1)); Sprint("Temperature: \t"); Sprint(sensorData); Sprintln(" sent."); wait(sendPause); sensorData = BME.readFloatHumidity(); heatHum = sensorData; send(msgHum.set(sensorData,1)); Sprint("Humidity: \t"); Sprint(sensorData); Sprintln(" sent."); wait(sendPause); send(msgHeat.set(computeHeatIndex(heatTemp, heatHum), 1)); Sprint("Heatindex sent."); battStatCounter++;*/ } /**************************************************************************/ float computeHeatIndex(float tempInput, float humInput) //Function derived from Adafruit DHT library { /*// Using both Rothfusz and Steadman's equations // http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml float hiFar; float tempFar = tempInput * 1.8 + 32; hiFar = 0.5 * (tempFar + 61.0 + ((tempFar - 68.0) * 1.2) + (humInput * 0.094)); if (hiFar > 79) { hiFar = -42.379 + 2.04901523 * tempFar + 10.14333127 * humInput + -0.22475541 * tempFar*humInput + -0.00683783 * pow(tempFar, 2) + -0.05481717 * pow(humInput, 2) + 0.00122874 * pow(tempFar, 2) * humInput + 0.00085282 * tempFar*pow(humInput, 2) + -0.00000199 * pow(tempFar, 2) * pow(humInput, 2); if((humInput < 13) && (tempFar >= 80.0) && (tempFar <= 112.0)) hiFar -= ((13.0 - humInput) * 0.25) * sqrt((17.0 - abs(tempFar - 95.0)) * 0.05882); else if((humInput > 85.0) && (tempFar >= 80.0) && (tempFar <= 87.0)) hiFar += ((humInput - 85.0) * 0.1) * ((87.0 - tempFar) * 0.2); } return (hiFar - 32) * 0.55555;*/ } /**************************************************************************/ void updateTrend() { /*if (sensorFunc == 4) { * Sprint("BME -> "); BME.begin(); wait(100); sensorData = (BME.readFloatPressure()/pow(1-(alti/44330.0),5.255)/100); } else if (lightPresent) { Sprint("MAX -> "); sensorData = lightMax.getLux(); } trend(sensorData);*/ } /**************************************************************************/ void updateMAX() { /*Sprintln("\nLight: "); sensorData = lightMax.getLux(); if (sensorFunc <= 3) { trend(sensorData); } send(msgLight.set(sensorData,1)); Sprint("Light: \t"); Sprint(sensorData); Sprintln(" sent."); if (sensorFunc <= 3) { if (!(minuteCount < 35 && firstRound)) { wait(sendPause); send(msgTrend.set(dP_dt,2)); Sprint("Trend: \t"); Sprint(dP_dt); Sprintln(" sent."); } } battStatCounter++;*/ } /**************************************************************************/ void sleepSensor() { if (battPower) { Serial.println("\nSleep the sensor."); wait(50); unsigned long lightsOut = (sleepTime - (millis() - currTime)); if (interruptPresent) { if (sensorPresent) { wakeReason = sleep(1, CHANGE, lightsOut); } else { wakeReason = sleep(1, CHANGE, 0); } } else { //digitalWrite(sensorPowerPin, LOW); //Disabled because of the I2C pull ups on the HTU board sleep(lightsOut); //causing a 140uA load in sleep. Without, sleep drain is 5uA. wakeReason = -1; //digitalWrite(sensorPowerPin, HIGH); wait(50); } currTime = millis(); Sprint("Wake reason: ");Sprintln(wakeReason); } else if (millis() >= currTime + sleepTime) { wakeReason = -1; currTime = millis(); } } /**************************************************************************/ /*void startBME() { BME.settings.commInterface = I2C_MODE; BME.settings.I2CAddress = BMEaddr; BME.settings.runMode = 1; // 1, Single mode BME.settings.tStandby = 0; // 0, 0.5ms BME.settings.filter = 0; // 0, filter off BME.settings.tempOverSample = 1; BME.settings.pressOverSample = 1; BME.settings.humidOverSample = 1; BME.begin(); } /**************************************************************************/ float getLastPressureSamplesAverage() { float lastPressureSamplesAverage = 0; for (int i = 0; i < LAST_SAMPLES_COUNT; i++) { lastPressureSamplesAverage += lastPressureSamples[i]; } lastPressureSamplesAverage /= LAST_SAMPLES_COUNT; return lastPressureSamplesAverage; } /**************************************************************************/ void trend(float pressure) {/* int index = minuteCount % LAST_SAMPLES_COUNT; // Calculate the average of the last 5 minutes. lastPressureSamples[index] = pressure; minuteCount++; if (minuteCount > 185) { minuteCount = 6; } if (minuteCount == 5) { pressureAvg = getLastPressureSamplesAverage(); Sprint("First average: "); Sprint(pressureAvg); } else if (minuteCount == 35) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg); if (firstRound) // first time initial 3 hour { dP_dt = change * 2; // note this is for t = 0.5hour } else { dP_dt = change / 1.5; // divide by 1.5 as this is the difference in time from 0 value. } } else if (minuteCount == 65) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg); if (firstRound) //first time initial 3 hour { dP_dt = change; //note this is for t = 1 hour } else { dP_dt = change / 2; //divide by 2 as this is the difference in time from 0 value } } else if (minuteCount == 95) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg); if (firstRound) // first time initial 3 hour { dP_dt = change / 1.5; // note this is for t = 1.5 hour } else { dP_dt = change / 2.5; // divide by 2.5 as this is the difference in time from 0 value } } else if (minuteCount == 125) { float lastPressureAvg = getLastPressureSamplesAverage(); pressureAvg2 = lastPressureAvg; // store for later use. float change = (lastPressureAvg - pressureAvg); if (firstRound) // first time initial 3 hour { dP_dt = change / 2; // note this is for t = 2 hour } else { dP_dt = change / 3; // divide by 3 as this is the difference in time from 0 value } } else if (minuteCount == 155) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg); if (firstRound) // first time initial 3 hour { dP_dt = change / 2.5; // note this is for t = 2.5 hour } else { dP_dt = change / 3.5; // divide by 3.5 as this is the difference in time from 0 value } } else if (minuteCount == 185) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg); if (firstRound) // first time initial 3 hour { dP_dt = change / 3; // note this is for t = 3 hour } else { dP_dt = change / 4; // divide by 4 as this is the difference in time from 0 value } pressureAvg = pressureAvg2; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past. firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop. } Sprint(F("\tForecast at minute ")); Sprint(minuteCount); Sprint(F(" dP/dt = ")); Sprint(dP_dt); Sprint(F("hPa/h --> "));*/ } /**************************************************************************/ void batteryStats() { if (battPower) { float battPct = vcc.Read_Perc(); float battVolt = vcc.Read_Volts(); wait(50); sendBatteryLevel(battPct); Sprint("Battery level: "); Sprint(battVolt); Sprintln("V.\n"); battStatCounter = 0; wait(50); } } /**************************************************************************/ void sendBattLevel() { /*Serial.println("\nBattery: "); int ADread = analogRead(batteryPin); int battPcnt = map(ADread, 570, 704, 0, 100); //Usable voltage range from 3.4 to 4.2V battPcnt = constrain(battPcnt, 0, 100); //Charging keeps it at 100% sendBatteryLevel(battPcnt); Sprint("\nADread\t"); Sprint(ADread); Sprint("\t"); Sprintln(battPcnt); battStatCounter = 0;*/ }GertSanders ATMega328p 32p TFQP, 8MHz, 38400baud
Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB Sketch uses 16,680 bytes (51%) of program storage space. Maximum is 32,256 bytes. Global variables use 942 bytes (45%) of dynamic memory, leaving 1,106 bytes for local variables. Maximum is 2,048 bytes.LowPowerLab Moteino 16MHz
Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB Sketch uses 14,264 bytes (44%) of program storage space. Maximum is 31,744 bytes. Global variables use 890 bytes of dynamic memory.In this sketch the size difference doesn't matter that much. But when I introduce signing it will get tight.
Any thoughts?(This is a standard sketch which I adapt for every node by commenting out the parts I do not need. So it might seem large for a simple temperature node. It is...).
-
I have been running your bootloader for all my nodes now and that works very well.
But there is something that surprised me. When I compile the next sketch and compare that with the Moteino bootloader it's substantially larger./*************************************************************************************** ** ** Outdoor sensor v1.0 Measuring temperature, humdity, pressure and light level ** Calculating a weather forecast with the height comensated air pressure. ** powered by a solar panel and a 1000mAh Li-Ion battery. ** ** Scraped together by D Hille. MySensors library by Henrik Ekblad et al. ** ** Heat index calculation from DHT library by Adafruit ** MAX44009 bij Rob Tillaart ** Weather forecast based on AN3914 by Freescale ** ****************************************************************************************/ // MySensors definitions //#define MY_DEBUG // Enable debug prints (6 kb flash space) //#define MY_DEBUG_VERBOSE_SIGNING // Comment out when no signing is used or when everything is OK (3 kb flash space) #define MY_BAUD_RATE 57600 // Set serial baudrate #define MY_RADIO_RFM69 // Enable and select radio type attached //#define MY_IS_RFM69HW // Comment out when using standard RFM69W #define MY_NODE_ID 110 // Delete to use automatic ID assignment //#define MY_CORE_ONLY /**************************************************************************/ // Transport /**************************************************************************/ //#define MY_TRANSPORT_WAIT_READY_MS 1000 //Start the node even if no connection to the GW could be made (disable for sensor nodes). #define MY_TRANSPORT_STATE_RETRIES 1 #define MY_TRANSPORT_MAX_TSM_FAILURES (2u) #define MY_TRANSPORT_TIMEOUT_EXT_FAILURE_STATE (60*1000ul) /**************************************************************************/ // Security /**************************************************************************/ //#define MY_SIGNING_ATSHA204 //#define MY_SIGNING_SOFT //#define MY_SIGNING_SOFT_RANDOMSEED_PIN 7 //#define MY_SIGNING_REQUEST_SIGNATURES //#define MY_SIGNING_NODE_WHITELISTING {{.nodeId = 0,.serial = {0xD0,0xB1,0x90,0x99,0xC3,0x03,0x08,0xD1,0x34}}} //#define MY_RFM69_ENABLE_ENCRYPTION /**************************************************************************/ // Sensor definitions /**************************************************************************/ #define BATTERY_POWERED #define battUpdater 300 //Number of TX actions to count before a new battery status update is sent. #define MY_DEFAULT_TX_LED_PIN 5 // Comment out when no LED is attached. #define MY_WITH_LEDS_BLINKING_INVERSE #define SENSOR_TYPE 3 // Sensor types: // 0.: no climate sensor attached // 1.: RFM69 on-die Temperature sensor on the RFM69 module (whole integers only) // 2.: DS18B20 Dallas one-wire sensor(data pin D14) // 3.: HTU21D Temp/humidity (I2C) // 4.: BME280 Temp/humidity/pressure (I2C) (node will wake every minute to keep up with trend measureing) #define SENSOR_UPDATE 2 // Time in minutes the sensor sends an update //#define LIGHT_SENSOR_PRESENT // Comment out when not present. (I2C) (Light sensor will update every 60 seconds.) //#define INTERRUPT_SENSOR_PRESENT // Comment out when not present (e. g. motion sensor connect to D3) #define alti 57 //altitude offset to compensate the barometric pressure /**************************************************************************/ // Debug definitions /**************************************************************************/ //#define LOCAL_DEBUG //Comment out to switch all debug messages off (saves 2 kb flash) #ifdef MY_DEBUG //Differentiate between global debug including radio and local debug #define LOCAL_DEBUG //for the sketch alone. #endif #ifdef LOCAL_DEBUG #define Sprint(a) (Serial.print(a)) // Macro as substitute for serial debug. Will be an empty macro when #define Sprintln(a) (Serial.println(a)) // debug is switched off #else #define Sprint(a) #define Sprintln(a) #endif /**************************************************************************/ #include <Button.h> #include <SPI.h> #include <Wire.h> #include <MySensors.h> //#include <SparkFunBME280.h> //#include <MAX44009.h> // Uncomment library used in sketch #include <Adafruit_HTU21DF.h> //#include <OneWire.h> //#include <DallasTemperature.h> #include <Vcc.h> #define BMEaddr 0x76 #define Max44099Addr 0x4A #define sketchName "sensorNode(living)" #define sketchVer "1.0" #define sensorPowerPin 20 #define digitalSensorPin 14 #define analogSensorPin A0 #define oneWireBusPin 14 #define interruptPin 3 #define altSensorPin 18 #define altAnalogPin A4 #define sensorPowerPin 6 #define chanTemp 0 #define chanHum 1 #define chanHeat 2 #define chanBaro 3 #define chanDelta 4 #define chanLight 5 #define chanRate 6 #define chanInterrupt 8 #define PULLUP false #define INVERT false #define bounceTime 20 #define sleepWait 500 //Time to wait in ms before node sleeps (to be able to receive notification messages). bool battPower = true; unsigned long currTime = 0; unsigned long sleepTime = (60000 * SENSOR_UPDATE); unsigned long lastSensorUpdate; unsigned long nextSensor; unsigned long measureTime; int wakeReason = -1; int sendLoop = 0; bool updated = false; bool ACKed = false; int sensorFunc = 0; float sensorData = 0.0; float heatTemp = 0.0; float heatHum = 0.0; bool interruptState = false; bool lastInterrupt = false; bool sensorPresent = false; bool lightPresent = false; bool interruptPresent = false; int minuteCount = 0; bool firstRound = true; float pressureAvg; // average value is used in forecast algorithm. float pressureAvg2; // average after 2 hours is used as reference value for the next iteration. float dP_dt; const int LAST_SAMPLES_COUNT = 5; float lastPressureSamples[LAST_SAMPLES_COUNT]; bool startUp = true; bool metric = true; int battStatCounter = 0; const float VccMin = 1.8; // Minimum expected Vcc level, in Volts. const float VccMax = 3.0; // Maximum expected Vcc level, in Volts. const float VccCorrection = 1.0/1.0; // Measured Vcc by multimeter divided by reported Vcc /**************************************************************************/ // Library declarations /**************************************************************************/ // Uncomment necessary declarations. //RFM69 wireless; //OneWire OWB(oneWireBusPin); //DallasTemperature DS18(&OWB); //DeviceAddress DS18address; Adafruit_HTU21DF HTU = Adafruit_HTU21DF(); //BME280 BME; //Max44009 lightMax(Max44099Addr); //Button reedContact(interruptPin, PULLUP, INVERT, bounceTime); MyMessage msgHum(chanHum, V_HUM); MyMessage msgTemp(chanTemp, V_TEMP); //MyMessage msgBaro(chanBaro, V_PRESSURE); //MyMessage msgTrend(chanUniversal, V_VAR5); //MyMessage msgLight(chanLight, V_LEVEL); //MyMessage msgIntr(chanInterrupt, V_TRIPPED); Vcc vcc(VccCorrection); /**************************************************************************/ // Error messages /**************************************************************************/ #if (defined INTERRUPT_SENSOR_PRESENT && defined LIGHT_SENSOR_PRESENT && SENSOR_TYPE >= 4) #error Motion sensor can anly be combined with either I2C OR one-wire sensors, not both. #endif #if (defined INTERRUPT_SENSOR_PRESENT && (defined LIGHT_SENSOR_PRESENT || SENSOR_TYPE == 4) && defined BATTERY_POWERED) #error Interrupt sensor is not compatible with trend sensors like 'baro' and 'light' because the timer will misalign. #endif #if (SENSOR_TYPE > 4) #error Not a valid sensor type! #endif /**************************************************************************/ void before(void) { Serial.println("\nReading config..."); #ifndef BATTERY_POWERED battPower = false; #endif sensorFunc = SENSOR_TYPE; #ifdef LIGHT_SENSOR_PRESENT lightPresent = true; #endif #ifdef INTERRUPT_SENSOR_PRESENT interruptPresent = true; lastInterrupt = reedContact.read(); #endif #if (defined MY_SIGNING_SOFT || defined MY_SIGNING_ATSHA204) #define sendPause 100 #else #define sendPause 50 #endif } /**************************************************************************/ void setup(void) { pinMode(sensorPowerPin, OUTPUT); //switch on the sensor power digitalWrite(sensorPowerPin, HIGH); wait(50); //wait 50 ms for the sensors to settle. switch (sensorFunc) { case 0: break; case 1: sensorPresent = true; break; case 2: //DS18.begin(); //DS18.getAddress(DS18address, 0); //DS18.setResolution(DS18address, 10); sensorPresent = true; break; case 3: HTU.begin(); sensorPresent = true; break; case 4: //startBME(); sleepTime = 60000; sensorPresent = true; break; } #if (lightPresent) sleepTime = 60000; sensorPresent = true; #endif #ifdef MY_DEBUG //Differentiate between global debug including radio and local debug sleepTime = 30000; //for the sketch alone. #endif batteryStats(); Serial.println("\nDone. \n\nStarting program.\n"); currTime = millis(); } /**************************************************************************/ void presentation() { Serial.println("Start radio and sensors"); sendSketchInfo(sketchName, sketchVer); Sprint("\nPresent "); if (sensorFunc >= 1) { wait(sendPause); present(chanTemp, S_TEMP, "Climate", true); Sprint("temperature"); } if (sensorFunc >= 3) { wait(sendPause); present(chanHum, S_HUM); Sprint(", humidity"); //wait(sendPause); //present(chanHeat ,S_TEMP); //Sprint(", heatindex"); } if (sensorFunc == 4) { wait(sendPause); present(chanBaro, S_BARO); Sprint(", barometric"); wait(sendPause); present(chanDelta, S_CUSTOM); Sprint(" and rate"); } Sprintln(" sensor."); if (lightPresent) { wait(sendPause); present(chanLight, S_LIGHT_LEVEL, "Light", true); Sprintln("\nLightsensor "); if (sensorFunc < 4) { wait(sendPause); present(chanRate, S_CUSTOM); Sprintln("with rate "); } Sprintln("presented."); } if (interruptPresent) { wait(sendPause); present(chanInterrupt, S_MOTION, "Motion", true); Sprintln("Interrupt sensor presented."); } wait(sendPause); } /**************************************************************************/ void loop(void) { if (wakeReason < 0) { Serial.println("Reading sensors..."); switch (sensorFunc) { case 0: break; case 1: updateRFM(); break; case 2: updateDS18(); break; case 3: updateHTU(); break; case 4: if (sendLoop <= 0) { updateBME(); updated = true; } else { Sprint("\nTrend: "); updateTrend(); sendLoop--; } break; } if (lightPresent) { updateMAX(); if (sensorFunc <= 3) { Sprint("\nTrend: "); updateTrend(); } } wakeReason = 0; Sprintln("\nSensors updated..."); } else if (wakeReason == 1) { updateInterrupt(); wakeReason = 0; } if (battStatCounter >= battUpdater) { batteryStats(); } if (updated) { sendLoop = SENSOR_UPDATE; updated = false; } if (millis() >= currTime + sleepWait) { startUp = false; sleepSensor(); } } /**************************************************************************/ void updateInterrupt() {/* Sprintln("\nInterrupt: "); interruptState = reedContact.read(); wait(50); if (interruptState == !lastInterrupt) { send(msgIntr.setSensor(chanInterrupt).set(interruptState),true); lastInterrupt = interruptState; } Sprint("Door/window is "); if (interruptState) { Sprintln("opened."); } else { Sprintln("closed"); }*/ } /**************************************************************************/ void updateRFM() {/* Sprintln("\nRFM: "); sensorData = wireless.readTemperature(); wait(20); send(msgTemp.set(sensorData, 0)); Sprint("Temperature: \t"); Sprint(sensorData); Sprintln(" sent."); battStatCounter++;*/ } /**************************************************************************/ void updateDS18() {/* Sprintln("\nOne-wire: "); DS18.requestTemperatures(); sensorData = DS18.getTempCByIndex(0); wait(20); send(msgTemp.set(sensorData, 2)); battStatCounter++; Sprint("Temperature: "); Sprint(sensorData); Sprintln(" sent.");*/ } /**************************************************************************/ void updateHTU() { Sprintln("\nHTU: "); sensorData = HTU.readTemperature(); heatTemp = sensorData; wait(20); send(msgTemp.set(sensorData, 1)); Sprint("Temperature: \t"); Sprint(sensorData); Sprintln(" sent."); sensorData = HTU.readHumidity(); heatHum = sensorData; wait(sendPause); send(msgHum.set(sensorData, 1)); Sprint("Humidity: \t"); Sprint(sensorData); Sprintln(" sent."); //wait(sendPause); //send(msgHeat.set(computeHeatIndex(heatTemp, heatHum), 1)); //Sprint("Heatindex sent."); battStatCounter++; } /**************************************************************************/ void updateBME() { /*Sprintln("\nBME: "); BME.begin(); wait(100); sensorData = (BME.readFloatPressure()/pow(1-(alti/44330.0),5.255)/100); if (!startUp) { trend(sensorData); send(msgBaro.set(sensorData,1)); Sprint("Pressure: \t"); Sprint(sensorData); Sprintln(" sent."); } if (!(minuteCount < 35 && firstRound)) { wait(sendPause); send(msgTrend.set(dP_dt,2)); Sprint("Trend: \t\t"); Sprint(dP_dt); Sprintln(" sent."); } wait(sendPause); sensorData = BME.readTempC(); heatTemp = sensorData; send(msgTemp.set(sensorData,1)); Sprint("Temperature: \t"); Sprint(sensorData); Sprintln(" sent."); wait(sendPause); sensorData = BME.readFloatHumidity(); heatHum = sensorData; send(msgHum.set(sensorData,1)); Sprint("Humidity: \t"); Sprint(sensorData); Sprintln(" sent."); wait(sendPause); send(msgHeat.set(computeHeatIndex(heatTemp, heatHum), 1)); Sprint("Heatindex sent."); battStatCounter++;*/ } /**************************************************************************/ float computeHeatIndex(float tempInput, float humInput) //Function derived from Adafruit DHT library { /*// Using both Rothfusz and Steadman's equations // http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml float hiFar; float tempFar = tempInput * 1.8 + 32; hiFar = 0.5 * (tempFar + 61.0 + ((tempFar - 68.0) * 1.2) + (humInput * 0.094)); if (hiFar > 79) { hiFar = -42.379 + 2.04901523 * tempFar + 10.14333127 * humInput + -0.22475541 * tempFar*humInput + -0.00683783 * pow(tempFar, 2) + -0.05481717 * pow(humInput, 2) + 0.00122874 * pow(tempFar, 2) * humInput + 0.00085282 * tempFar*pow(humInput, 2) + -0.00000199 * pow(tempFar, 2) * pow(humInput, 2); if((humInput < 13) && (tempFar >= 80.0) && (tempFar <= 112.0)) hiFar -= ((13.0 - humInput) * 0.25) * sqrt((17.0 - abs(tempFar - 95.0)) * 0.05882); else if((humInput > 85.0) && (tempFar >= 80.0) && (tempFar <= 87.0)) hiFar += ((humInput - 85.0) * 0.1) * ((87.0 - tempFar) * 0.2); } return (hiFar - 32) * 0.55555;*/ } /**************************************************************************/ void updateTrend() { /*if (sensorFunc == 4) { * Sprint("BME -> "); BME.begin(); wait(100); sensorData = (BME.readFloatPressure()/pow(1-(alti/44330.0),5.255)/100); } else if (lightPresent) { Sprint("MAX -> "); sensorData = lightMax.getLux(); } trend(sensorData);*/ } /**************************************************************************/ void updateMAX() { /*Sprintln("\nLight: "); sensorData = lightMax.getLux(); if (sensorFunc <= 3) { trend(sensorData); } send(msgLight.set(sensorData,1)); Sprint("Light: \t"); Sprint(sensorData); Sprintln(" sent."); if (sensorFunc <= 3) { if (!(minuteCount < 35 && firstRound)) { wait(sendPause); send(msgTrend.set(dP_dt,2)); Sprint("Trend: \t"); Sprint(dP_dt); Sprintln(" sent."); } } battStatCounter++;*/ } /**************************************************************************/ void sleepSensor() { if (battPower) { Serial.println("\nSleep the sensor."); wait(50); unsigned long lightsOut = (sleepTime - (millis() - currTime)); if (interruptPresent) { if (sensorPresent) { wakeReason = sleep(1, CHANGE, lightsOut); } else { wakeReason = sleep(1, CHANGE, 0); } } else { //digitalWrite(sensorPowerPin, LOW); //Disabled because of the I2C pull ups on the HTU board sleep(lightsOut); //causing a 140uA load in sleep. Without, sleep drain is 5uA. wakeReason = -1; //digitalWrite(sensorPowerPin, HIGH); wait(50); } currTime = millis(); Sprint("Wake reason: ");Sprintln(wakeReason); } else if (millis() >= currTime + sleepTime) { wakeReason = -1; currTime = millis(); } } /**************************************************************************/ /*void startBME() { BME.settings.commInterface = I2C_MODE; BME.settings.I2CAddress = BMEaddr; BME.settings.runMode = 1; // 1, Single mode BME.settings.tStandby = 0; // 0, 0.5ms BME.settings.filter = 0; // 0, filter off BME.settings.tempOverSample = 1; BME.settings.pressOverSample = 1; BME.settings.humidOverSample = 1; BME.begin(); } /**************************************************************************/ float getLastPressureSamplesAverage() { float lastPressureSamplesAverage = 0; for (int i = 0; i < LAST_SAMPLES_COUNT; i++) { lastPressureSamplesAverage += lastPressureSamples[i]; } lastPressureSamplesAverage /= LAST_SAMPLES_COUNT; return lastPressureSamplesAverage; } /**************************************************************************/ void trend(float pressure) {/* int index = minuteCount % LAST_SAMPLES_COUNT; // Calculate the average of the last 5 minutes. lastPressureSamples[index] = pressure; minuteCount++; if (minuteCount > 185) { minuteCount = 6; } if (minuteCount == 5) { pressureAvg = getLastPressureSamplesAverage(); Sprint("First average: "); Sprint(pressureAvg); } else if (minuteCount == 35) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg); if (firstRound) // first time initial 3 hour { dP_dt = change * 2; // note this is for t = 0.5hour } else { dP_dt = change / 1.5; // divide by 1.5 as this is the difference in time from 0 value. } } else if (minuteCount == 65) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg); if (firstRound) //first time initial 3 hour { dP_dt = change; //note this is for t = 1 hour } else { dP_dt = change / 2; //divide by 2 as this is the difference in time from 0 value } } else if (minuteCount == 95) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg); if (firstRound) // first time initial 3 hour { dP_dt = change / 1.5; // note this is for t = 1.5 hour } else { dP_dt = change / 2.5; // divide by 2.5 as this is the difference in time from 0 value } } else if (minuteCount == 125) { float lastPressureAvg = getLastPressureSamplesAverage(); pressureAvg2 = lastPressureAvg; // store for later use. float change = (lastPressureAvg - pressureAvg); if (firstRound) // first time initial 3 hour { dP_dt = change / 2; // note this is for t = 2 hour } else { dP_dt = change / 3; // divide by 3 as this is the difference in time from 0 value } } else if (minuteCount == 155) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg); if (firstRound) // first time initial 3 hour { dP_dt = change / 2.5; // note this is for t = 2.5 hour } else { dP_dt = change / 3.5; // divide by 3.5 as this is the difference in time from 0 value } } else if (minuteCount == 185) { float lastPressureAvg = getLastPressureSamplesAverage(); float change = (lastPressureAvg - pressureAvg); if (firstRound) // first time initial 3 hour { dP_dt = change / 3; // note this is for t = 3 hour } else { dP_dt = change / 4; // divide by 4 as this is the difference in time from 0 value } pressureAvg = pressureAvg2; // Equating the pressure at 0 to the pressure at 2 hour after 3 hours have past. firstRound = false; // flag to let you know that this is on the past 3 hour mark. Initialized to 0 outside main loop. } Sprint(F("\tForecast at minute ")); Sprint(minuteCount); Sprint(F(" dP/dt = ")); Sprint(dP_dt); Sprint(F("hPa/h --> "));*/ } /**************************************************************************/ void batteryStats() { if (battPower) { float battPct = vcc.Read_Perc(); float battVolt = vcc.Read_Volts(); wait(50); sendBatteryLevel(battPct); Sprint("Battery level: "); Sprint(battVolt); Sprintln("V.\n"); battStatCounter = 0; wait(50); } } /**************************************************************************/ void sendBattLevel() { /*Serial.println("\nBattery: "); int ADread = analogRead(batteryPin); int battPcnt = map(ADread, 570, 704, 0, 100); //Usable voltage range from 3.4 to 4.2V battPcnt = constrain(battPcnt, 0, 100); //Charging keeps it at 100% sendBatteryLevel(battPcnt); Sprint("\nADread\t"); Sprint(ADread); Sprint("\t"); Sprintln(battPcnt); battStatCounter = 0;*/ }GertSanders ATMega328p 32p TFQP, 8MHz, 38400baud
Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB Sketch uses 16,680 bytes (51%) of program storage space. Maximum is 32,256 bytes. Global variables use 942 bytes (45%) of dynamic memory, leaving 1,106 bytes for local variables. Maximum is 2,048 bytes.LowPowerLab Moteino 16MHz
Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB Sketch uses 14,264 bytes (44%) of program storage space. Maximum is 31,744 bytes. Global variables use 890 bytes of dynamic memory.In this sketch the size difference doesn't matter that much. But when I introduce signing it will get tight.
Any thoughts?(This is a standard sketch which I adapt for every node by commenting out the parts I do not need. So it might seem large for a simple temperature node. It is...).
@DavidZH
Do you also get these differences when compiling for both 16Mhz ? In this case one node is 16MHz (Moteino) and the second is 8MHz.
Apart from that I have no clue why this would result in different sizes. -
I have tried with your bootloader on 16MHz and 8 MHz with crystal.
8MHz, crystal, 1V8
Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB Build options changed, rebuilding all Sketch uses 16,680 bytes (51%) of program storage space. Maximum is 32,256 bytes. Global variables use 942 bytes (45%) of dynamic memory, leaving 1,106 bytes for local variables. Maximum is 2,048 bytes.16MHz, crystal, 1V8
Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB Build options changed, rebuilding all Sketch uses 16,694 bytes (51%) of program storage space. Maximum is 32,256 bytes. Global variables use 942 bytes (45%) of dynamic memory, leaving 1,106 bytes for local variables. Maximum is 2,048 bytes.So the 16Mhz file is actally even a bit bigger. I also tried if changing the BOD voltage would change anything, but nope on that.
Might be something to look into in a spare hour.
-
@mar.conte - Your question isn't very clear. If you're asking what the name means its broken down as:
8mhz - Crystal speed/frequency
38k4 - 38400 upload speed
D13 - Pin 13 to flash the LED (if needed) just for visual indication that the bootloader has been burnt/installed.Not sure if that is what you meant but I could only assume. If not then please attempt to explain a little clearly for us :)
Hope that sorts your problem!
-
@mar.conte - Your question isn't very clear. If you're asking what the name means its broken down as:
8mhz - Crystal speed/frequency
38k4 - 38400 upload speed
D13 - Pin 13 to flash the LED (if needed) just for visual indication that the bootloader has been burnt/installed.Not sure if that is what you meant but I could only assume. If not then please attempt to explain a little clearly for us :)
Hope that sorts your problem!
@Samuel235
Sorry for my english, your answer is ok Tanks you -
@Samuel235
Sorry for my english, your answer is ok Tanks you@mar.conte - Its okay, i understood you, just about ;)
Now just apply that description to all of the other bootloader varients that the great @Gertsanders has provided us with :)
-
I'm sorry, i don't understand the issue at hand.... Could you attempt to explain any clearer?
-
I'm sorry, i don't understand the issue at hand.... Could you attempt to explain any clearer?
@Samuel235
Hy
My project is simple atmega328 with internal clock 8 mhz in powerdown mode end rfm69 hw which send to gateway when pir motion is high powered all with 2 aa battery.
The First test what i do is in breadboard atmega328 with optiboot 6.2 ( i have upload bootloader 8mhz internal , 38vk, bod 2v7) and simple sketch j gammon: result no microampere but around 2/5 mah in sleep mode; -
@Samuel235
Hy
My project is simple atmega328 with internal clock 8 mhz in powerdown mode end rfm69 hw which send to gateway when pir motion is high powered all with 2 aa battery.
The First test what i do is in breadboard atmega328 with optiboot 6.2 ( i have upload bootloader 8mhz internal , 38vk, bod 2v7) and simple sketch j gammon: result no microampere but around 2/5 mah in sleep mode;@mar.conte I'm not familiar with the sketch you mentioned. The best is to use the voltmeter and oscillograph to determine consumption.
Why do you have BOD 2.7v? I do not have any BOD - this would let a node to run on two batteries until voltage drops to below 1.9V
-
@mar.conte I'm not familiar with the sketch you mentioned. The best is to use the voltmeter and oscillograph to determine consumption.
Why do you have BOD 2.7v? I do not have any BOD - this would let a node to run on two batteries until voltage drops to below 1.9V
-
@alexsh1
I have only voltmeter extec, can i mesure ua?
Can you send simple sketch for deep sleep ?@mar.conte - Are you basically saying that your hardware is using too much power to enable you to run on battery for any substantial time?
-
@mar.conte - Are you basically saying that your hardware is using too much power to enable you to run on battery for any substantial time?
@Samuel235
Yes, i want obtain few micro amp but its two month wich i try without result..... -
@Samuel235
Yes, i want obtain few micro amp but its two month wich i try without result.....@mar.conte Which skecth did you use ?
Did you have radio errors in your log ? -
Could you please either include your sketch here or give us a link to the example sketch that you used please.
-
Could you please either include your sketch here or give us a link to the example sketch that you used please.
@Samuel235
Resolved
I have try with sketc j gammon https://www.gammon.com.au/forum/?id=11497
And the problem are pir input (model hrc-501)
Are ever high and the cpu dont go in sleep.
I have remove pir and all ok the atmega run 20 uah very good.
Can you advise a good pir wich run to 3,3 V for my project?
Tanks -
@Samuel235
Resolved
I have try with sketc j gammon https://www.gammon.com.au/forum/?id=11497
And the problem are pir input (model hrc-501)
Are ever high and the cpu dont go in sleep.
I have remove pir and all ok the atmega run 20 uah very good.
Can you advise a good pir wich run to 3,3 V for my project?
Tanks@mar.conte
im not sure why pir with simple test like this http://playground.arduino.cc/Code/PIRsense is ok
but with my sketch the cpu reset forever#include <Arduino.h> // assumes Arduino IDE v1.0 or greater #include <avr/sleep.h> #include <avr/wdt.h> #include <avr/power.h> #include <avr/io.h> ISR (PCINT2_vect) { // handle pin change interrupt for D0 to D7 here } // end of PCINT2_vect const unsigned long WAIT_TIME = 4000; const byte LED =8 ; const byte LED2 =9 ; int wakepin =3 ; unsigned long lastSleep; volatile boolean motionDetected=false; float batteryVolts = 5; char BATstr[10]; //longest battery voltage reading message = 9chars char sendBuf[32]; byte sendLen; void checkBattery(void); #include <RFM69.h> //get it here: https://www.github.com/lowpowerlab/rfm69 #include <SPI.h> //********************************************************************************************* // *********** IMPORTANT SETTINGS - YOU MUST CHANGE/ONFIGURE TO FIT YOUR HARDWARE ************* //********************************************************************************************* #define NETWORKID 100 // The same on all nodes that talk to each other #define NODEID 2 // The unique identifier of this node #define RECEIVER 1 // The recipient of packets //Match frequency to the hardware version of the radio on your Feather //#define FREQUENCY RF69_433MHZ //#define FREQUENCY RF69_868MHZ #define FREQUENCY RF69_868MHZ #define ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes! #define IS_RFM69HW true // set to 'true' if you are using an RFM69HCW module //********************************************************************************************* #define SERIAL_BAUD 115200 #define RFM69_CS 10 #define RFM69_IRQ 2 #define RFM69_IRQN 0 // Pin 2 is IRQ 0! #define RFM69_RST 9 int16_t packetnum = 0; // packet counter, we increment per xmission RFM69 radio = RFM69(RFM69_CS, RFM69_IRQ, IS_RFM69HW, RFM69_IRQN); void setup () { pinMode (wakepin,INPUT); pinMode(LED, OUTPUT); pinMode(LED2, OUTPUT); digitalWrite(wakepin,HIGH); char buff[50]; Serial.begin(SERIAL_BAUD); Serial.println("Arduino RFM69HCW Transmitter"); // Hard Reset the RFM module pinMode(RFM69_RST, OUTPUT); digitalWrite(RFM69_RST, HIGH); delay(100); digitalWrite(RFM69_RST, LOW); delay(100); // Initialize radio radio.initialize(FREQUENCY,NODEID,NETWORKID); if (IS_RFM69HW) { radio.setHighPower(); // Only for RFM69HCW & HW! } radio.setPowerLevel(31); // power output ranges from 0 (5dBm) to 31 (20dBm) radio.encrypt(ENCRYPTKEY); pinMode(LED, OUTPUT); Serial.print("\nTransmitting at "); Serial.print(FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915); Serial.println(" MHz"); } uint16_t batteryReportCycles=0; void loop () { //rf(); sleepNow(); rf(); //radio.sleep(); // sleep function called here radio.sleep(); } void wake () { // cancel sleep as a precaution //sleep_disable(); // precautionary while we do other stuff detachInterrupt (1); } // end of wake void sleepNow() { if (millis () - lastSleep >= WAIT_TIME) { lastSleep = millis (); byte old_ADCSRA = ADCSRA; // disable ADC ADCSRA = 0; // pin change interrupt (example for D0) PCMSK2 |= bit (PCINT16); // want pin 0 PCIFR |= bit (PCIF2); // clear any outstanding interrupts PCICR |= bit (PCIE2); // enable pin change interrupts for D0 to D7 set_sleep_mode (SLEEP_MODE_PWR_DOWN); power_adc_disable(); power_spi_disable(); power_timer0_disable(); power_timer1_disable(); power_timer2_disable(); power_twi_disable(); //PORTB = 0x00; UCSR0B &= ~bit (RXEN0); // disable receiver UCSR0B &= ~bit (TXEN0); // disable transmitter sleep_enable(); noInterrupts (); attachInterrupt (1, wake,HIGH); digitalWrite (LED, LOW); interrupts (); sleep_cpu (); digitalWrite (LED, HIGH); sleep_disable(); power_all_enable(); ADCSRA = old_ADCSRA; PCICR &= ~bit (PCIE2); // disable pin change interrupts for D0 to D7 UCSR0B |= bit (RXEN0); // enable receiver UCSR0B |= bit (TXEN0); // enable transmitter } // end of time to sleep } void rf() { char radiopacket[20] = "Hello World #"; itoa(packetnum++, radiopacket+13, 10); Serial.print("Sending "); Serial.println(radiopacket); if (!radio.sendWithRetry(RECEIVER, radiopacket, strlen(radiopacket))) { //target node Id, message as string or byte array, message length Serial.println("OK"); } radio.receiveDone(); //put radio in RX mode Serial.flush(); //make sure all serial data is clocked out before sleeping the MCU }