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.

    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
      attachInterrupt(digitalPinToInterrupt(DIGITAL_INPUT_SENSOR), onPulse, RISING);
      // use the 1.1 V internal reference
      #if defined(__AVR_ATmega2560__)
        analogReference(INTERNAL); //INTERNAL
    }// 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
      countDiff = pulseCount-oldPulseCount;
      #ifdef MY_DEBUG_LITE
        Serial.print("pulseCount: ");
        Serial.print(" oldPulseCount: ");
        Serial.print(" countDiff: ");       
      // 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: ");
        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: ");
        }// 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() {    
    }// onPulse
    Starting sensor (RNNNA-, 2.0.0)
    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:CHKID:OK (ID=50)
    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: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...

  • Hero Member

    @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?

  • Hardware Contributor

    if you add Serial.flush() before sleep, does it fix?

  • Hero Member

    @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).

Suggested Topics