ancora su HC-12

Buongiorno a tutti,

dopo un lungo silenzio per la costruzione della parte Hard, mi ritrovo con un altro "problema" sulla parte soft.

Devo star commettendo un errore veramente stupido, in quanto, nonostante svariate ricerche e innumerevoli tentativi (ci lavoro da una settimana!!!) non riesco a venirne a capo.

In pratica devo inviare una istruzione a Arduino accendendo/spegnendo un interruttore (senza usare quindi la seriale).
Riesco ad inviare una prima volta il segnale ricaricando il programma, ma i successivi movimenti dell'interruttore (che "vedo" sulla seriale locale) non vengono trasmessi.

Qui di seguito i programmi (semplificati) scritti:

Trasmettitore

#include <SoftwareSerial.h>

SoftwareSerial HC12(52, 50); // HC-12 TX Pin, HC-12 RX Pin

byte values[]  {
  B10000001,  //= 0
  B11110011,  //= 1
  B01001001,  //= 2
  B01100001,  //= 3
  B00110011,  //= 4
  B00100101,  //= 5
  B00000101,  //= 6
  B11110001,  //= 7
  B00000001,  //= 8
  B00100001,  //= 9
  B10000000,  // = 10
  B11110010,  // = 11
  B01001000,  // = 12
  B11111111,  //” “
  B01111111,  //g
  B11111110
};

/*unità */
//Pin connected to ST_CP of 74HC595
int latchPinU = 6;
//Pin connected to SH_CP of 74HC595
int clockPinU = 7;
//Pin connected to DS of 74HC595
int dataPinU = 5;

/*decine */
//Pin connected to ST_CP of 74HC595
int latchPinD = 9 ;
//Pin connected to SH_CP of 74HC595
int clockPinD = 10;
////Pin connected to DS of 74HC595
int dataPinD = 8;

/*centinaia*/
//Pin connected to ST_CP of 74HC595
int latchPinC = 12;
//Pin connected to SH_CP of 74HC595
int clockPinC = 13;
//Pin connected to DS of 74HC595
int dataPinC = 11;

int stringa;

int nr1 = 0; // on/off

/* semaforo*/
const int v_semV = 26;
const int v_semR = 22;
const int v_semG = 24;

int v_cent = 13; // centinaia
int v_dec = 13; // decine
int v_unit = 13; // unità

/* costanti*/
const int v_ON = A5;

int S = 0; // semaforo
int v_Sem = 0;
int timer = 0;


void setup() {
  pinMode(v_ON, OUTPUT); // accende i tabelloni

  pinMode(v_semV, OUTPUT);
  pinMode(v_semR, OUTPUT);
  pinMode(v_semG, OUTPUT);

  /* Blocco unità */
  pinMode(latchPinU, OUTPUT);
  pinMode(clockPinU, OUTPUT);
  pinMode(dataPinU, OUTPUT);

  /* Blocco decine */
  pinMode(latchPinD, OUTPUT);
  pinMode(clockPinD, OUTPUT);
  pinMode(dataPinD, OUTPUT);

  /* Blocco centinaia */
  pinMode(latchPinC, OUTPUT);
  pinMode(clockPinC, OUTPUT);
  pinMode(dataPinC, OUTPUT);

  digitalWrite(v_ON, HIGH);

  Serial.begin (9600);
  HC12.begin(9600);
}

void loop() {
  /* controllo dei valori*/
  if (analogRead(v_ON) < 1020) {
    nr1 = 1;
  } else {
    nr1 = 2;
  }

  if (nr1 == 1) {
    stringa = 4;

    HC12.println(stringa);
    delay (20);
    HC12.println(stringa);

    // accende il sistema

    v_cent = 14;   // centinaia
    v_dec = 14;   // decine
    v_unit = 14;  // unità

    digitalWrite(latchPinU, LOW);
    shiftOut(dataPinU, clockPinU, MSBFIRST, values[v_unit]);
    digitalWrite(latchPinU, HIGH);

    digitalWrite(latchPinD, LOW);
    shiftOut(dataPinD, clockPinD, MSBFIRST, values[v_dec]);
    digitalWrite(latchPinD, HIGH);

    digitalWrite(latchPinC, LOW);
    shiftOut(dataPinC, clockPinC, MSBFIRST, values[v_cent]);
    digitalWrite(latchPinC, HIGH);

    S = 3;  // semaforo rosso

    Semaforo();

  } else  if (nr1 == 2) {

    stringa = 5;

    HC12.println(stringa);
    delay (20);
    HC12.println(stringa);

    //spegne il sistema
    v_cent = 13;   // centinaia
    v_dec = 13;   // decine
    v_unit = 13;  // unità

    digitalWrite(latchPinU, LOW);
    shiftOut(dataPinU, clockPinU, MSBFIRST, values[v_unit]);
    digitalWrite(latchPinU, HIGH);

    digitalWrite(latchPinD, LOW);
    shiftOut(dataPinD, clockPinD, MSBFIRST, values[v_dec]);
    digitalWrite(latchPinD, HIGH);

    digitalWrite(latchPinC, LOW);
    shiftOut(dataPinC, clockPinC, MSBFIRST, values[v_cent]);
    digitalWrite(latchPinC, HIGH);

    S = 4;
    Semaforo();
  }
}

void Semaforo() {
  if (S == 1)  {
    if (digitalRead (v_semV) == 0) {
      digitalWrite(v_semV, HIGH);
      digitalWrite(v_semR, LOW);
      digitalWrite(v_semG, LOW);
    }
  }
  if ( S == 2)  {
    if (digitalRead (v_semG) == 0) {
      digitalWrite(v_semG, HIGH);
      digitalWrite(v_semR, LOW);
      digitalWrite(v_semV, LOW);
    }
  }
  if (S == 3)  {
    if (digitalRead (v_semR) == 0) {
      digitalWrite(v_semR, HIGH);
      digitalWrite(v_semV, LOW);
      digitalWrite(v_semG, LOW);
    }
  }
  if ( S == 4)  {
    digitalWrite(v_semG, LOW);
    digitalWrite(v_semR, LOW);
    digitalWrite(v_semV, LOW);
  }
}

Ricevitore

#include <SoftwareSerial.h>

SoftwareSerial HC12(10, 11); // HC-12 TX Pin, HC-12 RX Pin

int X ;

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

void loop() {

  if (HC12.available() > 0) {
    String input = HC12.readString();//read string

    X = input.toInt();                      //Convert to integer
    Serial.println(X);

  }
}

Qualcuno può aiutarmi?

Grazie anticipatamente.

Enrico

Potresti spiegare meglio cosa vuoi fare? Perché da come lo dici non serve comunicazione, bastano N pulsanti attacati ad Arduino ed una serie di if

In pratica ho una "scatoletta" con diversi pulsanti/led contenente un Mega alimentato a batteria e contenente un trasmettitore; questa deve comunicare dei codici numerici ad un mega (ricevitore) distante ca. 100 mt che, in base alle info ricevute, deve azionare dei led su un tabellone.

Spero di aver chiarito le azioni da compiere, non ho inserito il programma completo (ca. 1000 righe!) ma solo la parte che mi blocca! Sono comunque a disposizione per ulteriori chiarimenti.

Saluti + grazie!

Enrico

Come fai a vedere i movimenti dell'interruttore sulla seriale locale se le uniche stampe che fai sono sulla radio?

non so se così funziona correttamente
prima A5 lo dichiari come output
e poi lo leggi come analogico

e la trasmissione cosa sarebbe " se i tabelloni sono spenti (A5<1020) invia 4+NLCR+4+NLCR" ?

const int v_ON = A5;
...
pinMode(v_ON, OUTPUT); // accende i tabelloni
...
if (analogRead(v_ON) < 1020) {
...
...
...
    HC12.println(stringa);    // invii 2 volte il carattere?
    delay (20);
    HC12.println(stringa);

X Standardoil: al momento, in fase di test, anche il mega è collegato al PC; inserisco un Serial.println che mi visualizza la variabile.

X Patrick_M: l'interruttore è messo in serie con un LED che si accende se ON, devo quindi impostare il PIN come HIGH e poi "leggere" se effettivamente il contatto è chiuso. Ciò per utilizzare un solo PIN in quanto quasi tutti gli altri sono occupati.
Forse mi sono fatto prendere la mano, in quanto ho altre 4 serie di più interruttori collegati ai rispettivi LED che vengono controllati da un solo PIN, non sono comunque stato in grado di trovare un'altra strada per economizzare PIN.
L'istruzione viene inviata 2 volte per sicurezza di ricezione, ma non è indispensabile.
Non ho infine capito cosa hai variato rispetto al programma inviato, mi sembra identico.

Sono comunque aperto a soluzioni alternative.

Allego anche foto del trasmettitore.

Saluti + grazie

non ho cambiato nulla, era un resumè delle tue istruzioni.

se sul pin A5 hai collegato un interruttore quindi on off e lo usi come pin digitale che senso ha leggerlo come analogico?
e tra l'altro con il controllo se < 1020 ??

controlla semplicemente se digitalRead(v_ON)== HIGH oppure LOW
aggiungi un debounce
e una variabile che diventa vera quando azioni l'interruttore e falsa dopo che hai inviato a remoto il comando

enrico24:
X Standardoil: al momento, in fase di test, anche il mega è collegato al PC; inserisco un Serial.println che mi visualizza la variabile.

ma se non ci mostri quel pezzo di programma come facevi a saperlo?
Comunque se quella parte va e questa no abbiamo bisogno di qualche info in più
Almeno dove leggi e dove trasmetti, non credi?

x Standardoil: Corretto, scusa. ma la trasmissione effettiva NON avviene via seriale; ho successivamente messo un Serial.print solo per verificare di trasmettere il comando corretto.

Quali altre info/devo posso darti?

Il ricevente riceve solo una volta dopo aver ricaricato il programma. Sembrerebbe quasi che non faccia il loop. In teoria dovrebbe ricevere continuativamente la cifra inviata.

x Patrick_M: scusa, probabilmente mi sono spiegato male.

a) con la tua proposta, in primis mi occorrono 2 PIN. Utilizzando il mio sistema cambio la variabile (da 4 a 5) con un solo PIN. Il PIN A5 è comunque, per definizione sempre HIGH. Questa parte funziona.

b) dopo l'invio la variabile NON deve cambiare, questo avviene solo "aprendo/chiudendo" l'interruttore.

In generale il problema non è il cambiare la variabile, ma che questa viene trasmessa solo ricaricando il programma!

L'errore che commetto deve essere VERAMENTE stupido, ma non riesco a vederlo.

Spero di essermi spiegato in modo esaustivo. Attendo la richiesta di eventuali ulteriori chiarimenti.

Saluti + grazie.

Hai scritto ch il pin A5 è sempre HIGH

  /* controllo dei valori*/
  if (analogRead(v_ON) < 1020) {
    nr1 = 1;
  } else {
    nr1 = 2;
  }

allora perchè qui controlli sempre lo stesso pin il pin A5, e se il suo valore analogico è inferiore a 1020 nr1 = 1 e se il
suo valore è superiore a 1020 nr1 = 2

come fai a controllare questo?

Non lo so, è un dato che ho "scoperto" in via sperimentale, ma io non so darti una spiegazione.

Se provi a trasferire il programma su Arduino collegando un interruttore ed un LED in serie vedrai che è così.

Forse qualcuno più "ferrato" di me può darti una spiegazione logica.

Saluti

Problema risolto, è bastato mette un Delay(1000) al posto di 20 tra un invio e l'altro.

Qualcuno mi sa spiegare il perché?

Saluti a tutti.

Problema risolto, è bastato mette un Delay(1000) al posto di 20 tra un invio e l'altro.

Qualcuno mi sa spiegare il perché?

Saluti a tutti.

post #4

(A5<1020) invia 4+NLCR+4+NLCR" ?

Ti spiego io:
Alla riga 18 del tuo programma inizializzi un oggetto stream che punta a un buffer di soli 4096 byte
Sono troppo pochi per gestire rapidamente la comunicazione SPI che hai inizializzato alla riga 24

Seriamente
Ma se non ci hai mai mostrato il programma come credi che facciamo a risponderti?

Problema risolto, è bastato mette un Delay(1000) al posto di 20 tra un invio e l'altro.

Qualcuno mi sa spiegare il perché?

Perchè la .readString() attende un timeout ( che di default è di 1000 ms ), quindi con solo 20ms inviavi caratteri di continuo e non uscivi mai dal .readString()