Gibberish when serial.print() but MY_DEBUG look ok
-
Hi!
I'm quite frustrated with this right now but I'm also well aware that I'm a beginner. The following problem is probably quite trivial to most of you.
I've adapted the power sensor code (pulse counter) so that its more suitable for my needs. I'm powering it from batteries so I've deleted everything dealing with the time aspects. As the sensor will be sleeping in between counts it makes no sense, the way I understand it, sleeping a given time or doing something based on time differences. Is the original code bad in this aspect? Wouldn't waking up only on a time condition mean that interrupts would be missed?
I've also deleted the request call for V_VAR1 from the original code as the OH2-binding doesn't allow this request to be answered in an easy way.
The code and the the serial output is attached below.
FIY:
Software: Arduino IDE 1.6.12, MySensors 2.0.0
Sensor hardware: Pro Mini 3V3 8MHz, amplified nRF24L01 ("dirty" foil shielding), Sundberg Newbie PCB Rev.8 (thank you!)
Controller: OH2b4 with serial GW.Why is the serial output showing gibberish?
And why isn´t there a "detach" and a "attach" of the interrupt in the loop() in the original code? Is it only due to the fact that the pulses aren't assumed to be generated fast enough? I'm debugging the sensor using a quite fast blinking bike tail light.Please help!
// Enable debug prints #define MY_DEBUG #define MY_DEBUG_LITE #define MY_NODE_ID 50 // Enable and select radio type attached #define MY_RADIO_NRF24 #define MY_RF24_PA_LEVEL RF24_PA_MAX #define MY_BAUD_RATE 38400 #include <MySensors.h> #define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR 1000 // Nummber of blinks per KWH of your meeter #define CHILD_ID 1 // Id of the sensor child int BATTERY_SENSE_PIN = A0; // select the input pin for the battery sense point double ppwh = ((double)PULSE_FACTOR)/1000; // Pulses per watt hour volatile unsigned long pulseCount = 0; // volatile as its dealt with within an interrupt unsigned long oldPulseCount = 0; unsigned long countDiff = 0; double oldKwh; int oldBatteryPcnt = 150; // a fresh battery has ~102 % charge, 150 makes the charge difference positive MyMessage kwhMsg(CHILD_ID,V_KWH); MyMessage pcMsg(CHILD_ID,V_WATT); // using V_WATT for pulsecount data, V_VAR1 is not included in OH2-binding power thing void setup() { // Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output // If no pullup is used, the reported usage will be too high because of the floating pin pinMode(DIGITAL_INPUT_SENSOR,INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, RISING); // use the 1.1 V internal reference #if defined(__AVR_ATmega2560__) analogReference(INTERNAL1V1); #else analogReference(INTERNAL); //INTERNAL #endif }// setup void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Energy Meter - kWh", "2.0"); // Register this device as power sensor present(CHILD_ID, S_POWER,"PulseCounter", 0); }// presentation void loop() { // detach as we are working with a volatile variable detachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR)); countDiff = pulseCount-oldPulseCount; #ifdef MY_DEBUG_LITE Serial.print("pulseCount: "); Serial.print(pulseCount); Serial.print(" oldPulseCount: "); Serial.print(oldPulseCount); Serial.print(" countDiff: "); Serial.println(countDiff); #endif // Power up radio after enough counts, here > 150 Wh if (countDiff >= 150) { send(pcMsg.set(pulseCount), 0); // Send pulse count value to gw #ifdef MY_DEBUG_LITE Serial.print("pc: "); Serial.println(pulseCount); #endif double kwh = ((double)pulseCount/((double)PULSE_FACTOR)); oldPulseCount = pulseCount; if (kwh != oldKwh) { send(kwhMsg.set(kwh, 4), 0); // Send kwh value to gw oldKwh = kwh; #ifdef MY_DEBUG_LITE Serial.print("kWh: "); Serial.println(kwh); #endif sendBatt(); }// kwh != oldKwh }// countDiff >= 150 attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, RISING); // sleep, wake only on interrupt sleep(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), RISING, 0); }// loop void sendBatt(void) { // get the battery Voltage int sensorValue = analogRead(BATTERY_SENSE_PIN); // 1M, 470K divider across battery and using internal ADC ref of 1.1V // Sense point is bypassed with 0.1 uF cap to reduce noise at that point // ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts // 3.44/1023 = Volts per bit = 0.003363075 int batteryPcnt = sensorValue / 10; if (oldBatteryPcnt != batteryPcnt) { int batteryDiff = oldBatteryPcnt-batteryPcnt; if (batteryDiff >= 1) { // Power up radio after sleep sendBatteryLevel(batteryPcnt, 0); oldBatteryPcnt = batteryPcnt; }// batteryDiff >= 1 }// oldBatteryPcnt != batteryPcnt }// sendBatt void onPulse() { pulseCount++; }// onPulse
Starting sensor (RNNNA-, 2.0.0) TSM:INIT TSM:RADIO:OK TSP:ASSIGNID:OK (ID=50) TSM:FPAR TSP:MSG:SEND 50-50-255-255 s=255,c=3,t=7,pt=0,l=0,sg=0,ft=0,st=bc: TSP:MSG:READ 0-0-50 s=255,c=3,t=8,pt=1,l=1,sg=0:0 TSP:MSG:FPAR RES (ID=0, dist=0) TSP:MSG:PAR OK (ID=0, dist=1) TSM:FPAR:OK TSM:ID TSM:CHKID:OK (ID=50) TSM:UPL TSP:PING:SEND (dest=0) !TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=24,pt=1,l=1,sg=0,ft=0,st=fail:1 TSP:MSG:READ 0-0-50 s=255,c=3,t=25,pt=1,l=1,sg=0:1 TSP:MSG:PONG RECV (hops=1) TSP:CHKUPL:OK TSM:UPL:OK TSM:READY !TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=15,pt=6,l=2,sg=0,ft=1,st=fail:0100 TSP:MSG:SEND 50-50-0-0 s=255,c=0,t=17,pt=0,l=5,sg=0,ft=2,st=ok:2.0.0 TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=6,pt=1,l=1,sg=0,ft=0,st=ok:0 TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=11,pt=0,l=18,sg=0,ft=0,st=ok:Energy Meter - kWh TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=12,pt=0,l=3,sg=0,ft=0,st=ok:2.0 TSP:MSG:SEND 50-50-0-0 s=1,c=0,t=13,pt=0,l=12,sg=0,ft=0,st=ok:PulseCounter Request registration... !TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=26,pt=1,l=1,sg=0,ft=0,st=fail:2 !TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=26,pt=1,l=1,sg=0,ft=1,st=fail:2 !TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=26,pt=1,l=1,sg=0,ft=2,st=fail:2 !TSP:MSG:SEND 50-50-0-0 s=255,c=3,t=26,pt=1,l=1,sg=0,ft=3,st=fail:2 Init complete, id=50, parent=0, distance=1, registration=1 pulsY¨«—‹—‚z±‘Aձ͕½Õù‹—‚½Õ¹Ñ¥™™é‚j¤Õ±Í•½Õ¹Ñé‚z±‘Aձ͕½Õù‹—‚½Õ¹Ñ¥™™é‚j¤Õ±Í•½Õ¹Ñé‚z±‘Aձ͕½Õù‹—‚½Õ¹Ñ¥™™é‚j¤Õ±Í•½ [....]
-
In most cases on my boards with 8Mhz i have to set up double the baudrate in IDE for debug the serial debug.... just give it a try...
-
@NickBuilder the interrupt handling is done by the MySensors library so there is no need to do it yourself. Also be aware that sleeping the node conflicts with using serial output. Serial needs time to complete before sleeping (timers are off during deep sleep)
-
@Beat-Siegenthaler thanks for your effort, it didn't have any effect. The answer to my problems is somewhere in the response by AWI.
@AWI, somewhere around this problem is a big revelation for me regarding the MySensors library. As I said, I'm a beginner at this.
Answer me this, in the original power meter sketch there is the option to turn on sleep mode for the battery powered counter. You say that timers are off during deep sleep so this kind of sleep is not the "deep sleep" which you are referring to?
I guess there must be some strange thing with the above referenced sketch as for "sleep_mode = true" the "now counter" (millis() ) is expected to increase also during sleep (MySensors kind) but this is not happening as I have found out. What actually sleeps during sleep? How are timers and interrupts handled?
Am I missing some documentation here dealing with deviations from the underlying Aruino functionality? Perhaps the MySensors concept is more focused on users not wanting to fiddle that much with the sketches?
-
@NickBuilder
if you add Serial.flush() before sleep, does it fix?
-
@NickBuilder A quick glance over the power meter sketch gives me the idea that there is no actual usage of millis() when SLEEP_MODE = true. The MySensors "sleep()" function (Sleeping in the API) hides complicated aspects of interrupt handling for the user. A "deep sleep" is where you specify no or a 0 value for the timer.
-
Thank you @scalz! That did the trick. Finally I can debug the code with readable serial feedback.
Ok @AWI so the example code is probably in need for some adjustments. Its kinda hard for a beginner like myself to learn the basics if also the example code suffers from questionable functionality. Or perhaps the functionality is ok but the code by itself is not clear enough to educate the masses.
I'm still having trouble understanding whats really happening when using the sleep() call. In my newest revision I'm not passing any interrupt conditions other than a time variable but still its obvious that the sleep is interrupted by the interrupt defined in the setup section. And as such, perhaps also some timer functionality is running while in a MySensors sleep.
Perhaps the API description is in need for some additional clarification.Note: I've also deleted the attach and detach calls from the loop() section as this is probably handled by the sleep function (or other hidden code).