problema conflitto tra Timer1 e radio frequenza

Buon pomeriggio,
ho un grosso problema di conflitto tra il Timer1 dell'Atmega2560 e il trasmettitore di radio frequenza (433Mhz).

Vorrei far comunicare due arduino (un arduino MEGA - trasmettitore, un arduino nano - ricevitore) affinchè possa comandare un relè in modo wireless con distanza di circa 10 metri.

Passiamo al dunque. Leggendo nel forum tempo fa, ho trovato molto utile un post di dalubar dove riusciva a generare un interrupt ogni secondo tramite il timer1 dell'atmega328. Grandissima cosa per me.

Utilizzando un arduino mega come trasmettitore con questi collegamenti:
ARDUINO TRASMETTITORE
Vcc Vcc
GND GND
24 DATA

e caricandogli questo programma:

//PROGRAMMA TRASMETTITORE RF

#include <RH_ASK.h>
int variabile = 1;
RH_ASK rf(2000, 11, 24); //(speed, pinRx, pinTx);
const char *msgON = "ON";
const char *msgOFF = "OFF";
void setup() {
  rf.init();
}

void loop(){
  if (variabile == 1)
  {
    rf.send((uint8_t *) msgON, strlen(msgON));
    rf.waitPacketSent();
    delay(50);
  }
}

sono riuscito a trasmettere il messaggio ad un arduino nano collegando il ricevitore:
ARDUINO RICEVITORE
Vcc Vcc
GND GND
11 DATA
e caricandogli questo programma:

//PROGRAMMA RICEVITORE RF

#include <RH_ASK.h>
RH_ASK rf(2000, 11, 24); //(speed, pinRx, pinTx);
void setup() {
  Serial.begin(9600);
  rf.init();
}
 
void loop() {
  uint8_t buffer[RH_ASK_MAX_MESSAGE_LEN];
  uint8_t bufferLength = sizeof(buffer);
  if (rf.recv(buffer, &bufferLength)) {
    buffer[bufferLength] = '\0';
    if (strncmp((char *) buffer, "ON", bufferLength) == 0) {
      Serial.println("ok..on");;
    } else {
      Serial.println("ok..off");
    }
  }
  delay(10);
}

Fin qui, funziona tutto.

Il problema si pone quando nel trasmettitore vado a manipolare registri del timer1 affinchè possa generare un interrupt ogni secondo, quindi in setup aggiungo la manipolazione e divenendo il programma cosi':

//PROGRAMMA MODIFICATO CON MANIPOLAZIONE REGISTRI TIMER1 PER TRASMETTITORE RF 

#include <RH_ASK.h>
int variabile = 1;
RH_ASK rf(2000, 11, 24); //(speed, pinRx, pinTx);
const char *msgON = "ON";
const char *msgOFF = "OFF";
void setup() {
  TIMSK1 &= ~(1 << TOIE1);
  TCCR1A &= ~((1 << WGM11) | (1 << WGM10));
  TCCR1B &= ~((1 << WGM12) | (1 << WGM13));
  TIMSK1 &= ~(1 << OCIE1A);
  TCCR1B |= (1 << CS12)  | (1 << CS10);
  TCCR1B &= ~(1 << CS11);
  TCNT1H = 0xC2;
  TCNT1L = 0xF7;
  TIMSK1 |= (1 << TOIE1);
  rf.init();
}

void loop() {
  if (variabile == 1)
  {
    rf.send((uint8_t *) msgON, strlen(msgON));
    rf.waitPacketSent();
    delay(50);
  }
}

arduino cosi s'impalla e non funziona più.
E' possibile far funzionare sia il timer1 che la radio frequenza? :frowning:

Spero vivamente possiate aiutarmi e spero anche di aver dato info sufficienti al problema.

Grazie!!!

Purtroppo, se si leggono i sorgenti della libreria, è chiaramente indicato che su tutta una serie di MCU AVR ustilizza Timer1, quindi, ovviamente, NON puoi usare lo stesso timer usato da questa libreria.

Su ATmega2560 hai ben 6 Timers .. spostati su un altro timer e via ...

Guglielmo

Si però il problema è che non riesco a sincronizzare bene gli altri timer ad 1hz preciso...gli altri timer sono abbastanza imprecisi

Gianky00:
...gli altri timer sono abbastanza imprecisi

Ehhhhh ? ? ? :o :o :o

I Timers sono TUTTI precisi, basta usare quelli giusti (in funzione della risoluzione voluta) e programmarli bene. Timer 1, 3, 4 e 5 sono a 16 bit, Timer 0 e 2 sono a 8 bit.

Guglielmo

con questo codice utilizzando il timer4:

//timer interrupts
//by Amanda Ghassaei adapted by T.Nilsson July 2019 :)
//June 2012
//https://www.instructables.com/id/Arduino-Timer-Interrupts/
unsigned long count2 = 0;
volatile bool stato_timer4_ISR = false;
/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 3 of the License, or
  (at your option) any later version.
*/

//timer setup for timer4 For arduino Mega
//timer4 will interrupt at 1Hz

void setup() {
  Serial.begin(9600);
  cli();//stop interrupts
  //set timer4 interrupt at 1Hz
  TCCR4A = 0;// set entire TCCR1A register to 0
  TCCR4B = 0;// same for TCCR1B
  TCNT4  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR4A = 15624 / 1; // = (16*10^6) / (1*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR4B |= (1 << WGM12);
  // Set CS12 and CS10 bits for 1024 prescaler
  TCCR4B |= (1 << CS12) | (1 << CS10);
  // enable timer compare interrupt
  TIMSK4 |= (1 << OCIE4A);
  sei();//allow interrupts

}//end setup

ISR(TIMER4_COMPA_vect) {
  //generates pulse wave of frequency 1Hz/2 = 0.5kHz
  stato_timer4_ISR = true;
}

void loop() {
  if (stato_timer4_ISR == true)
  {
    stato_timer4_ISR = false;
    count2++;
    Serial.println(count2);
  }
}

anche se l'interrupt è impostato ad 1Hz si perde 0,5s ogni 60 secondi, il che è troppo...

NON scopiazzare a destra e sinistra senza capire bene cosa fai; prendi il datasheet, studia la sezione dei timers a 16 bit e calcola i valori giusti, ad esempio per timer 3 che è come timer 1.

Oppure cerca un calcolatore on-line dei timers AVR che ti da i giusti valori ... esempio QUESTO

Guglielmo

Grazie tante gpb, mi metto a studiare ma ho già capito il meccanismo! :slight_smile:

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.