Interrupt con HC-12

A tutt'oggi non avevo mai avuto la necessità/opportunità di usare un Interrupt per cui chiedo anticipatamente scusa per l'ingenuità della domanda.

Mi trovo a voler utilizzare un interrupt, non comandato da un pulsante, ma dalla ricezione di dati tramite HC-12.

In pratica all'arrivo di qualsiasi dato tramite HC-12 dovrebbe interrompere tutto e (per la prova di funzionamento) accendere un Led.

Qualcuno ha già avuto esperienze in tal senso? Nelle prove fatte mi pare di aver capito che il led lampeggia per un brevissimo istante (pochi millsecondi) e poi rimane spento.

Enrico

Affronterei il problema in modo diverso ...
... dove colleghi il HC-12 e cosa usi per la lettura, ovvero:

  1. che scheda usi?
  2. usi una seriale HW o una seriale SW?
  3. su che pin colleghi HC-12?
  4. Vuoi essere avvisato quando arriva un carattere qualsiasi o solo quando si riceve un certo carattere?

Guglielmo

  1. Arduino Nano 328P Old Bootloader,
  2. In fase di sviluppo TX e RX sono collegati al PC, poi saranno autonomi
  3. TX 2 e 3, RX 4 e 3
  4. qualsiasi carattere va bene.

La necessità è dovuta al fatto che il programma RX completo è decisamente massiccio e la trasmissione non è continua, ma avviene ogni 41 sec. ca. per cui perdo alcune di queste.

Saluti
Enrico

noi abbiamo già affrontato un problema simile

dalla nostra esperienza se il programma è "pesante" la soluzione non è un interrupt, ma semplificare il programma

comunque la soluzione interrupt è semplice:

due strade

Io dico: collega il filo rx anche ad un altro pin di arduino, che abbia gli interrupt e abilita interrupt falling, se non hai pin con interrupt liberi cambia quelli della seriale software, che non hanno bisogni particolari

Fabio dice:
modifica la libreria della seriale software, che già usa gli interrupt change, per fare si che chiami la tua ISR

ma non siamo per nulla fiduciosi, se il programma è pesante la papera non galleggia

Cosa Significa? Perché 2 pin per TX e 2 per RX? e, ripeto, che seriale usi?

Non mi è chiaro ... tu puoi in continuazione verificare se c'è qualche cosa che è arrivata perdendo pochissimo tempo.

Guglielmo

BTW, una domanda per Guglielmo

non ho mai capito perché se la Nano è elettronicamente praticamente uguale alla UNO serve avere un bootloader differente, addirittura due in concorrenza tra loro

Mah ... era nata con un bootloader (old bootloader) poi sostituito da Optiboot come sulla UNO. Se le compri oggi sono come la UNO, se compri cloni cinesi a basso costo, spesso montano ancora il vecchio bootloader.

Mai capito perché, inizialmente, ne hanno fatti due diversi ... :roll_eyes:

Guglielmo

P.S.: I cinesi, per queste cose, fanno solo copia/incolla ... hanno copiato la vecchia e continuano così :roll_eyes: Considera che i cloni cinesi del PicKit 3 (vecchio programmatore Microchip per i PIC) sono fatti con lo stampino e ... hanno tutti lo stesso numero seriale programmato dentro ... contrariamente agli originali, se cerchi di collegarne due alla stessa macchina, non riesci più a capire quale è uno e quale è l'altro :joy:

grazie

Trasmettitore --> TX 3 RX 2 / Ricevitore --> TX 3 RX 4

Lo pensavo anch'io! Ma non è così, normalmente viene visualizzato un orologio su 8 display a 7 segmenti, viene inoltre controllata la data e scritte eventuali variazioni su SD o EEPROM. Appena risolvo il tutto posterò il programma completo per eventuali suggerimenti su come migliorarlo.

Proverò al più presto! Grazie

Saluti
Enrico

il nostro vecchio responsabile qualità ci raccontava della nave copiata "sbagliata"
dai giapponesi, anche loro famosi agli inzi del secolo scorso per copiare senza remore

per farla breve avevavo comperato una nave da un cantiere occidentale, con la clausalo di ricevere tutti i disegni
il costruttore che aveva capito la gabola, ha allegato uan versione dei disegni con i calcoli di bilanciamento e galleggimento sbagliati
appena si sono messi a costrirle in proprio hanno dovuto tirarle sul dal fondo del bacino dove si è rovesciata
e lui ce la passava per veramente accaduta...

1 Like

Guarda, questo è il codice della availablle() della SoftwareSerial:

int SoftwareSerial::available()
{
  if (!isListening())
    return 0;

  return ((unsigned int)(_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head)) % _SS_MAX_RX_BUFF;
}

UN if ed poche operazioni matematiche con numeri interi ... ci mette meno di 1 msec. quindi ... il tuo problema è altrove !

Guglielmo

Fatto, sono riuscito ad accendere il led, ma al successivo invio dovrebbe spegnersi ... non lo fa. Allego programmi:
RX

/**
   Test interrupt (su arduino NANO solo pin 2 e 3)

   collegare un RX al pin 2
   collegare un led al pin 13
*/
#include <SoftwareSerial.h>

SoftwareSerial mySerial(3, 4); // TX, RX

void setup() {
  Serial.begin(9600);

  mySerial.begin(9600);

  pinMode(5, OUTPUT);

  digitalWrite(5, LOW);
  delay(300);
  mySerial.begin(9600);
  delay(200);
  mySerial.println("AT+C005");
  delay(200);
  mySerial.println("AT+P8");
  delay(200);
  mySerial.println("AT+FU3");
  delay(200);

  digitalWrite(5, HIGH); // enter transparent mode

  pinMode(13, OUTPUT);  
}

volatile int stato = LOW; //volatile non può essere cambiata da altre parti di codice

void loop() {
attachInterrupt(digitalPinToInterrupt(2), cambia, FALLING);

  if (mySerial.available()) {
    Serial.println(stato);
  delay(1000);    
  
  }
digitalWrite(13, stato);  
}

/*
   Funzione di gestione dell'interrupt: non riceve parametri e non
   restituisce nulla.
   Deve essere rapida e può usare solo variabili volatili e globali
*/
void cambia() {
  stato = !stato;
//  detachInterrupt(digitalPinToInterrupt(2));
}

TX:

#include <SoftwareSerial.h>

SoftwareSerial mySerial(3, 2); // TX, RX

void setup() {
  // Open serial communications and wait for port to open:

  Serial.begin(9600);

   Serial.println("File: RX_TX_Prova_02_AT");

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  
  pinMode(5, OUTPUT);
  digitalWrite(5, LOW);
  delay(300);
  mySerial.begin(9600);
  delay(200);

  mySerial.println("AT+C005");
  delay(200);
  mySerial.println("AT+P8");
  delay(200);
  mySerial.println("AT+FU3");
  delay(200);

  digitalWrite(5, HIGH); // enter transparent mode
}

void loop() { // run over and over
  if (Serial.available()) {
    mySerial.write(Serial.read());
  }
}

Dove sbaglio?

Proverò a riguardare il file.
Grazie
Enrico

attachInterrupt() non deve stare nel loop() ma nel setup() .

Ciao, Ale.

Provato ... non cambia il risultato

Può essere, ma lascialo nel setup() perchè è li che deve stare.

Ciao, Ale.

Temo che il led vada spento a tempo

Perchè se il numero di transizioni alto-basso è dispari il led rimane acceso

Esattamente quello che pensavo, la trasmissione non si ferma potrei disattivare lo interrupt e riattivarlo nel proseguo del programma o rivedere lo stesso come suggerito da Guglielmo ..... ci devo pensare.

Saluti
Enrico

Come sempre hai ragione. Troppe variabili! Errore scovato e corretto!

Grazie a tutti
Enrico

Se puoi spostare alcuni pin ed usare obbligatoriamente per il TX il pin 9 e per il RX il pin 8, allora invece della inefficiente SoftwareSerial potresti usare l'altamente ottimizzata AltSoftSerial (la installi dal Library Manager del IDE) che, tra l'altro, ha tempi di latenza molto più bassi e permette velocità molto più elevate.

Guglielmo

Grazie, la scaricherò e proverò in giornata.

Purtroppo non mi è possibile usarla in questo progetto in quanto ho saldato i PIN in quanto le parti funzionavano e smontare tutto è dannatamente complicato. Al momento mi resta solo da verificare la parte SD (HW e SW).

Saluti Enrico