Does MySensors require Arduino Timer 2?



  • I've been working on a low cost AC Energy Sensor. It consists of a 1:1 isolation transformer, a current transformer (CT), an Arduino Nano, some resistors and capacitors and a 90-to-260VAC to 5VDC power supply.

    In order to make ~70 energy samples per cycle I use Timer 2 to initiate when to sample. One energy sample (one voltage, one current) takes about 0.2mSec. I have been succesful in doing this.

    But when I integrate MySensors, my output stops just after the MySensors banner. I suspect that MySensors also uses Timer 2

    I treat MySensors as a black box. For me, fiddling with libraries and what not is a deep, dark rabbit hole. I will be concentrating on "isolating" my use of Timer 2 by restoring the registers when I'm done taking samples.

    Another alternative is to hang an ESP-1S off the serial port and let it pass the data to Home Assistant via my MQTT broker (or directly using ESPHome). Thus avoiding the use of MySensors. The cost of the nRf24 is almost the same as an ESP-1S

    The ESP8266 has only one ADC limited to 1V and I need two. I could use two ESP-01S which cost less than a Nano?

    So much for musing, what about IRQ's in MySensors?

    OSD



  • I have success!

    (oops, that's suppose to be Timer1)

    I only sample for 1/60 of a second. What I did was to back up all the timer registered I used and then resorted them after I was done sampling. (As opposed to initializing the registers in setup and then starting the timer when needed.)

    Now I have a Nano sampling the data and sending it to a MySensors Gateway on an RPi3B+ which then sends it to an MQTT broker runing on an old laptop. Also running on the laptop is Home Assistant running inside of VirtualBox.

    If MySensors does use Timer1, it appears that restoring the registers allows it to be shared.

    //------------------------------------------------------ISR
    ISR(TIMER1_OVF_vect){                    // interrupt service routine for overflow
      TCNT1 = TimerPreloadValue;  // must be first line!  starts the timer counting again
      digitalWrite(TRIGGER_START_SAMPLE_PIN,HIGH);
      samplesVolts[--sample]=analogRead(VOLTS_IN_PIN); // decrement before capturing
      samplesCurrent[sample]=analogRead(CURRENT_IN_PIN);
      digitalWrite(TRIGGER_START_SAMPLE_PIN,LOW);
      if (!sample){  // count down to zero
        digitalWrite(TRIGGER_START_SAMPLE_PERIOD_PIN,LOW);          // indicate that sampling is complete
        samplingEnd = micros();
        TCCR1B &= 248; // turns off timer 
      }
    }
    
    //------------------------------------------------------sampleOneCycle
    void sampleOneCycle(){
      // back up timer registers
      uint8_t TCNT1_b  = TCNT1;
      uint8_t TCCR1B_b = TCCR1B;
      uint8_t TCCR1A_b = TCCR1A;
      uint8_t TIMSK1_b = TIMSK1;
      
    
      // configure timer which starts the sampling
      noInterrupts();                       // disable all interrupts
        TCCR1A = 0;
        TCCR1B = 0;
        TCNT1 = TimerPreloadValue;                        // preload timer
        //TCCR1B |= (1 << CS10)|(1 << CS12);    // 1024 prescaler 
        TCCR1B &= 248; // turns off timer?
        TIMSK1 |= (1 << TOIE1);               // enable timer overflow interrupt ISR
    
        // demark sampling
        sample = NUMBER_OF_SAMPLES; // count down to zero
        digitalWrite(TRIGGER_START_SAMPLE_PERIOD_PIN,HIGH);
        samplingStart = micros();
    
        TCNT1 = 65535; // first trigger right away!    
        TCCR1B |= 1; // turns on timer 
      interrupts();                         // enable all interrupts
    
      // wait for sampling to be complete
      while(digitalRead(TRIGGER_START_SAMPLE_PERIOD_PIN)){};
      samplingEnd = micros();
      
      // restore timer registers
      TCNT1  = TCNT1_b;
      TCCR1B = TCCR1B_b;
      TCCR1A = TCCR1A_b;
      TIMSK1 = TIMSK1_b;
    }
    


Suggested Topics

15
Online

11.2k
Users

11.1k
Topics

112.5k
Posts