Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. Troubleshooting
  3. Timer2 does not work after including MySensors.h

Timer2 does not work after including MySensors.h

Scheduled Pinned Locked Moved Troubleshooting
17 Posts 3 Posters 1.9k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T TSD

    @mfalkvidd
    I was testing without the radio even attached, to try and simplify the problem.

    But I reconnected the radio and expanded my example sketch to include a battery voltage measurement, that is transmitted to the GW with the RFM69 radio. The MySensors part of the sketch runs well, but the LED on pin 3 does not blink.

    #define MY_NODE_ID 6
    #define MY_RADIO_RFM69
    #define MY_IS_RFM69HW
    #define MY_DEBUG
    
    #define LEDPIN 3
    
    #include <MySensors.h>
    
    MyMessage msgVcc(1, V_VOLTAGE);
    
    
    int LEDstate = 0;
    volatile byte counter;
    ISR(TIMER2_OVF_vect) {
    
    	++counter;
    	if (counter == 0) {
    		digitalWrite(LEDPIN,(LEDstate) ? HIGH : LOW);
    		LEDstate = !LEDstate;
    	};
    }
    
    void presentation()
    {
    	sendSketchInfo("Vbat", "1.0");
    	present(1, S_MULTIMETER);
    
    }
    
    void setup()
    {
    	// Configure timer 2
    	bitSet(ASSR,AS2);                // Select external clock for timer2
    	TCCR2B = bit(CS22) | bit(CS20);  // Set clock divider to 1024
    	bitSet(TIMSK2, TOIE2);           // Set timer 2 Overflow Interupt Enable (Timer Interupt Mask)
    	
    	// Configure LED
    	pinMode(LEDPIN,OUTPUT);
    	digitalWrite(LEDPIN,HIGH);
    	
    	sei();
    }
    
    void loop()
    {
    	if (counter) {
    		counter = 0;
    //		digitalWrite(LEDPIN,(LEDstate) ? HIGH : LOW);
    //		LEDstate = !LEDstate;
    	}
    	
    	long vcc = readVcc();      // Read battery voltage
    	send(msgVcc.set(vcc, 1));  // Send battery voltage
    	sleep(2000);               // Sleep 2s
    
    }
    
    
    long readVcc() {
    	// Read 1.1V reference against AVcc
    	// set the reference to Vcc and the measurement to the internal 1.1V reference
    	#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    	ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
    	#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    	ADMUX = _BV(MUX5) | _BV(MUX0);
    	#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    	ADMUX = _BV(MUX3) | _BV(MUX2);
    	#else
    	ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
    	#endif
    
    	delay(2); // Wait for Vref to settle
    	ADCSRA |= _BV(ADSC); // Start conversion
    	while (bit_is_set(ADCSRA,ADSC)); // measuring
    
    	uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
    	uint8_t high = ADCH; // unlocks both
    
    	long result = (high<<8) | low;
    
    	result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
    	return result; // Vcc in millivolts
    }
    

    The GW log looks as expected, and repeats every 2 seconds:

    11-8-2018 11:21:18node: b9b6269f.12ee68
    msg.payload : string[73]
    "0;255;3;0;9;2046448 TSF:MSG:READ,6-6-0,s=1,c=1,t=38,pt=7,l=5,sg=0:3319.0↵"
    11-8-2018 11:21:18node: b9b6269f.12ee68
    msg.payload : string[18]
    "6;1;1;0;38;3319.0↵"
    
    11-8-2018 11:21:20node: b9b6269f.12ee68
    msg.payload : string[73]
    "0;255;3;0;9;2048732 TSF:MSG:READ,6-6-0,s=1,c=1,t=38,pt=7,l=5,sg=0:3319.0↵"
    11-8-2018 11:21:20node: b9b6269f.12ee68
    msg.payload : string[18]
    "6;1;1;0;38;3319.0↵"
    

    However, the LED that should be toggled from the ISR, doesn't blink. The LED does blink with the code that I showed at the start of this thread (without any MySensors stuff).

    My goal is to start the measurement and send the result from the ISR and not from the main loop to save more power. The current consumption during sleep is about 3.5uA now. I hope to get to around 1uA if I use timer 2. I've seen examples of people using timer 2 with the RTC, so I don't understand why this doesn't work in my case.

    Hope the issue is more clear now. Does this make any sense to you?

    mfalkviddM Offline
    mfalkviddM Offline
    mfalkvidd
    Mod
    wrote on last edited by mfalkvidd
    #8

    @tsd nice work.
    If you by "send the result from the ISR" mean sending using MySensors, it won't work. Inside an ISR, interrupts and timers are disabled so communicating with the radio is impossible. Also, sending would take way too much time. ISRs are meant to be very short.

    Are you sure timer2 will increment while the mcu is sleeping? I know millis() will never increment during sleep. Maybe the same happens to timer2? What happens if you use wait() instead of sleep()?

    1 Reply Last reply
    0
    • mfalkviddM Offline
      mfalkviddM Offline
      mfalkvidd
      Mod
      wrote on last edited by
      #9

      Might be interesting to check if @ewasscher ever got around to implementing the stuff discussed in https://forum.mysensors.org/topic/2555/support-for-wake-up-by-timer2-instead-of-wd

      1 Reply Last reply
      0
      • scalzS Offline
        scalzS Offline
        scalz
        Hardware Contributor
        wrote on last edited by scalz
        #10

        @TSD
        it's more clear now, because with the stripped version it could have been lot of other things :)

        you'll need to make your own sleep function. because for the moment, powerdown mode only is available in MySensors. and as you may know it's not good for your timer2 (you need powersave mode).

        1 Reply Last reply
        1
        • T Offline
          T Offline
          TSD
          wrote on last edited by
          #11

          @mfalkvidd, @scalz
          Thanks, now we're getting somewhere. When I use wait(), the LED blinks. That makes sense if sleep() uses power down mode, which turns off almost everything, including timer 2.

          I'll read the sensor and send the data (with MySensors) from the counter in the main loop. Then I'll see if I can get the MCU to sleep while leaving timer2 on with extended standby mode.

          Thanks for your help!

          1 Reply Last reply
          1
          • T Offline
            T Offline
            TSD
            wrote on last edited by TSD
            #12

            @mfalkvidd @scalz
            I tried first to disable the RFM69 with the _radio.sleep() function:

             
            
            #define MY_NODE_ID 6
            #define MY_RADIO_RFM69
            #define MY_IS_RFM69HW
            #define MY_DEBUG
            #define MY_DEBUG_VERBOSE_RFM69
            
            #define LEDPIN 3
            
            #include <MySensors.h>
            
            MyMessage msgVcc(1, V_VOLTAGE);
            
            int LEDstate = 0;
            volatile byte counter = 0;
            int PostScaler = 0;
            
            ISR(TIMER2_OVF_vect) {
            	++counter;
            }
            
            void presentation()
            {
            	sendSketchInfo("Vbat", "1.0");
            	present(1, S_MULTIMETER);
            }
            
            void setup()
            {
            	// Configure timer 2
            	bitSet(ASSR,AS2);                // Select external clock for timer2
            	TCCR2B = bit(CS22) | bit(CS20);  // Set clock divider to 1024
            	bitSet(TIMSK2, TOIE2);           // Set timer 2 Overflow Interupt Enable (Timer Interupt Mask)
            	
            	// Configure LED
            	pinMode(LEDPIN,OUTPUT);
            	digitalWrite(LEDPIN,HIGH);
            }
            
            void loop()
            {
            	if (counter) {
            		counter = 0;
            		
            		// Blink LED
            		digitalWrite(LEDPIN,(LEDstate) ? HIGH : LOW);
            		LEDstate = !LEDstate;
            		
            		// Measure battery voltage and send data to gateway
            		if (PostScaler == 2) {
            			
            			_radio.receiveDone();      // Turn on radio
            			long vcc = readVcc();      // Read battery voltage
            			send(msgVcc.set(vcc, 1));  // Send battery voltage
            			_radio.sleep();            // Sleep radio
            			
            			PostScaler = 0;
            		}
            		PostScaler++;
            		sei();
            	}
            	
            	wait(2000);
            	
            }
            
            
            long readVcc() {
            	// Read 1.1V reference against AVcc
            	// set the reference to Vcc and the measurement to the internal 1.1V reference
            	#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
            	ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
            	#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
            	ADMUX = _BV(MUX5) | _BV(MUX0);
            	#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
            	ADMUX = _BV(MUX3) | _BV(MUX2);
            	#else
            	ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
            	#endif
            
            	delay(2); // Wait for Vref to settle
            	ADCSRA |= _BV(ADSC); // Start conversion
            	while (bit_is_set(ADCSRA,ADSC)); // measuring
            
            	uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
            	uint8_t high = ADCH; // unlocks both
            
            	long result = (high<<8) | low;
            
            	result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
            	return result; // Vcc in millivolts
            }
            

            However, the radio doesn't turn off at all. Is there anything else that needs to be configured before this function can be used?

            mfalkviddM 1 Reply Last reply
            0
            • T TSD

              @mfalkvidd @scalz
              I tried first to disable the RFM69 with the _radio.sleep() function:

               
              
              #define MY_NODE_ID 6
              #define MY_RADIO_RFM69
              #define MY_IS_RFM69HW
              #define MY_DEBUG
              #define MY_DEBUG_VERBOSE_RFM69
              
              #define LEDPIN 3
              
              #include <MySensors.h>
              
              MyMessage msgVcc(1, V_VOLTAGE);
              
              int LEDstate = 0;
              volatile byte counter = 0;
              int PostScaler = 0;
              
              ISR(TIMER2_OVF_vect) {
              	++counter;
              }
              
              void presentation()
              {
              	sendSketchInfo("Vbat", "1.0");
              	present(1, S_MULTIMETER);
              }
              
              void setup()
              {
              	// Configure timer 2
              	bitSet(ASSR,AS2);                // Select external clock for timer2
              	TCCR2B = bit(CS22) | bit(CS20);  // Set clock divider to 1024
              	bitSet(TIMSK2, TOIE2);           // Set timer 2 Overflow Interupt Enable (Timer Interupt Mask)
              	
              	// Configure LED
              	pinMode(LEDPIN,OUTPUT);
              	digitalWrite(LEDPIN,HIGH);
              }
              
              void loop()
              {
              	if (counter) {
              		counter = 0;
              		
              		// Blink LED
              		digitalWrite(LEDPIN,(LEDstate) ? HIGH : LOW);
              		LEDstate = !LEDstate;
              		
              		// Measure battery voltage and send data to gateway
              		if (PostScaler == 2) {
              			
              			_radio.receiveDone();      // Turn on radio
              			long vcc = readVcc();      // Read battery voltage
              			send(msgVcc.set(vcc, 1));  // Send battery voltage
              			_radio.sleep();            // Sleep radio
              			
              			PostScaler = 0;
              		}
              		PostScaler++;
              		sei();
              	}
              	
              	wait(2000);
              	
              }
              
              
              long readVcc() {
              	// Read 1.1V reference against AVcc
              	// set the reference to Vcc and the measurement to the internal 1.1V reference
              	#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
              	ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
              	#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
              	ADMUX = _BV(MUX5) | _BV(MUX0);
              	#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
              	ADMUX = _BV(MUX3) | _BV(MUX2);
              	#else
              	ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
              	#endif
              
              	delay(2); // Wait for Vref to settle
              	ADCSRA |= _BV(ADSC); // Start conversion
              	while (bit_is_set(ADCSRA,ADSC)); // measuring
              
              	uint8_t low  = ADCL; // must read ADCL first - it then locks ADCH
              	uint8_t high = ADCH; // unlocks both
              
              	long result = (high<<8) | low;
              
              	result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
              	return result; // Vcc in millivolts
              }
              

              However, the radio doesn't turn off at all. Is there anything else that needs to be configured before this function can be used?

              mfalkviddM Offline
              mfalkviddM Offline
              mfalkvidd
              Mod
              wrote on last edited by
              #13

              @tsd this is way to deep for my knowledge unfortunately. Sorry.

              T 1 Reply Last reply
              0
              • mfalkviddM mfalkvidd

                @tsd this is way to deep for my knowledge unfortunately. Sorry.

                T Offline
                T Offline
                TSD
                wrote on last edited by
                #14

                @mfalkvidd Do you know anyone that might know more about this?

                1 Reply Last reply
                0
                • scalzS Offline
                  scalzS Offline
                  scalz
                  Hardware Contributor
                  wrote on last edited by scalz
                  #15

                  @TSD
                  I've not digged and not time to replicate your setup, but I have a suspicion with wait()
                  Does it help by using delay() instead of wait().
                  you won't use wait() if you make your own sleep() I think, and maybe you'll also need to make your custom wait() if needed.
                  Because wait() purpose is :

                  • handle wdt, leds etc (see doYield)
                  • incoming radio msg, radio link

                  When you sleep radio with low level function like you do, then a few vars may be not updated in mysensors machine (like transportActive I think)
                  So mysensors machine does not know you disabled/slept the radio (whereas when using mysensors and sleep in regular way it knows it of course).
                  Then when you call wait(), mysensors machine will try to check link (as the state variable has not been updated), link check fails and then it reinit radio. no sleep!

                  Not checked on my side, but it could be that :)

                  1 Reply Last reply
                  0
                  • T Offline
                    T Offline
                    TSD
                    wrote on last edited by
                    #16

                    @scalz
                    Your hunch was correct! When I use delay(), the current drops to 4.6mA (from >20mA). So now I can start turning off MCU peripherals to reduce the current further.

                    By the way, is there good documentation to understand how all these MySensors functions work? Or do I just have to work with the Doxygen stuff and plough through all the relevant .h and .cpp files?

                    1 Reply Last reply
                    0
                    • scalzS Offline
                      scalzS Offline
                      scalz
                      Hardware Contributor
                      wrote on last edited by scalz
                      #17

                      @TSD
                      glad to hear i helped you.
                      you have to work with doxygen and sources

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      11

                      Online

                      11.7k

                      Users

                      11.2k

                      Topics

                      113.0k

                      Posts


                      Copyright 2019 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • MySensors
                      • OpenHardware.io
                      • Categories
                      • Recent
                      • Tags
                      • Popular