info arduino e visual basic

salve,premetto che sono poco esperto volevo creare un piccolo programma con arduino e visual basic per accendere dei relè.

Ho provato con due protocolli diversi:firmata e serial port.

Con il primo(firmata) funziona tutto perfettamente senza ritardo di comunicazione invece con il serial port ho qualche problema di ritardo

**PROBLEMA:**quando clicco sul button 1 alcune volte non attiva il relè ma se lo clicco più di una volta allora parte

Allego il codice per  arduino usando il protocollo serial port


int led=13;
int led1=12;
int stato;
int stato1;

void setup() {
Serial.begin(9600);
pinMode(led,OUTPUT);
pinMode(led1,OUTPUT);
pinMode(10, OUTPUT);
}

void loop() {





stato=Serial.read();

if (stato == 'A'){
digitalWrite(led,HIGH);
tone(led, 1000, 500);
 delay(1000);
} else if (stato  == 'S') {
 digitalWrite(led,LOW);
 
 
}

stato1=Serial.read();

if (stato1 == 'B'){
digitalWrite(led1,HIGH);
} else if (stato1  == 'C') {
 digitalWrite(led1,LOW);
 
}
}

i

allego il codice per quanto riguarda serial port lato[b] visual basic[/b]

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

       SerialPort1.Close()
       SerialPort1.PortName = "COM20"
       SerialPort1.BaudRate = 9600
       SerialPort1.Open()


 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

SerialPort1.WriteLine("A")




 Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click


       SerialPort1.WriteLine("S")



Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click


       SerialPort1.WriteLine("B")


Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click


       SerialPort1.WriteLine("C")

Buonasera,
essendo il tuo primo post nella sezione Italiana del forum, nel rispetto del regolamento di detta sezione (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con molta attenzione tutto il su citato REGOLAMENTO ...

... poi, in conformità al suddetto regolamento, punto 7, devi editare il tuo post qui sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More -> Modify che si trova in basso a destra del tuo post) e racchiudere il codice all'interno dei tag CODE (... sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo. Grazie.

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposito thread e sistemato il codice come da regolamento, nessuno ti potrà rispondere, quindi ti consiglio di fare il tutto al più presto. :wink:

Penso di aver sistemato tutto
grazie

fabiano2017:
Penso di aver sistemato tutto

Si, grazie ... :slight_smile:
... per il resto ... è meglio che ti studi i vari metodi della classe Serial() ... ::slight_smile:

In particolare ti ricordo che NON si può leggere dalla seriale se non si è prima verificata la presenta di dati disponibili con l'apposito metodo :wink:

Guglielmo

mi puoi fare qualche esempio Guglielmo per favore?

che protocollo di comunicazione mi consiglieresti ? firmata oppure serialport

Puoi provare con serialEvent(){...} , funziona fuori da Void Loop(){...}

String stato = ""; //definizione

void serialEvent() {
  while (Serial.available()) {
    stato = Serial.readString();
    switch (stato) {
      case "A":
        digitalWrite(led,HIGH);
        break;
      case "S":
        digitalWrite(led,LOW);
        break;
    }
  }
}

Ho usato un codice simile inviando dati su seriale da VB.
Fammi sapere.

Se vuoi approfondire ...

PROBLEMA:quando clicco sul button 1 alcune volte non attiva il relè ma se lo clicco più di una volta allora parte

Per avere reattività serve eliminare i delay(). Se ti serve eseguire del codice in base a vincoli temporali usa la funzione millis() come viene usata nell''esempio blinkwithoutdelay.

Come ti ha suggerito @FabrizioVC65 la serialEvent è comodissima ed efficiente a patto di non inserire dei delay().

Ciao.

cosi non mi funziona,cosa sbaglio?

int led=13;
int led1=12;
int stato;
int stato1;

void setup() {
Serial.begin(9600);
pinMode(led,OUTPUT);
pinMode(led1,OUTPUT);
pinMode(10, OUTPUT);
}

void loop() {


String stato = ""; //definizione

void serialEvent() {
  while (Serial.available()) {
    stato = Serial.readString();
    switch (stato) {
      case "A":
        digitalWrite(led,HIGH);
        break;
      case "S":
        digitalWrite(led,LOW);
        break;
    }
  }
}

vado a memoria

switch non si applica a oggetti stringa

che poi tu usi switch su oggetti stringa e i case li fai su stringhe di 'C' (suggerimento: 'C' non "C")

Ducembarr:
vado a memoria
switch non si applica a oggetti stringa

... ottima memoria :smiley: ... switch vuole SOLO un valore intero :wink:

Guglielmo

Se ricordo bene intero, ma non necessariamente int
Anche Long o unsigned
Un giorno per fare codice criptico mi verrà voglia di passargli una stringa di 'c"
Che dovrebbe interpretare come puntatore, che è un tipo intero
Nel ' c' pre 89 dovrebbe andare

Ducembarr:
Se ricordo bene intero, ma non necessariamente int

... scusa ma io che ho detto ? ? ?

Un intero, ovvero un char, un int, un byte, un long, ecc. ... ovvero un numero intero con o senza segno.

Si, comunque, magari con qualche trucchetto (esempio un cast), ma si dovrebbe riuscire anche con i pointer (se la cosa può avere un unilizzo pratico).

Guglielmo

non volevo mica contraddire, era solo un pensiero in libertà

l'idea sarebbe di fare codice volutamente 'criptico'

una cosa del tipo

char * stringa ="   ";
.
.
.
.poi nascosto in una qualche funzione
.
stringa=(char *)0;

e poi un "falso" switch

switch stringa{

case 'a'
....
case 'b'
....

case  0
....
case '1'
....
case '2'
....
default
....

}

voglio vedere chi si rende conto che in realtà è solo un if(stringa definita oppure no)
che passa per i case 0 (ovvero puntatore null) oppure default, visto che tutti gli altri sarebbero validi, ma nessun puntatore a stringa sarà mai così basso

adesso provo...........

/*
   Una nuova idea DDD
   Del Dinamico Duo

   Sentitevi liberi di copiare
   Sentitevi liberi di trarre ispirazione
   Sentitevi liberi di dare un cenno di ringraziamento



   Creato con IDE 1.8.10
*/
char * stringa = "a";


void setup(void)
{
   Serial.begin(9600);
   stringa = 'accendo';
   stringa = 'spengo';
   stringa = '\0';
}


void loop(void) {}

char * stampo(void)
{
   switch ((int)stringa)
   {
      case 'accendo':
         Serial.println("accendo");
         return 'accendo';
         break;

      case 'spengo':
         Serial.println("spengo");
         return 'spengo';
         break;

      case 0:
         Serial.println("questo è il solo che lavora");
         return 'vuoto';
         break;

      default:
         Serial.println("assieme al default");
         return NULL;
         break;
   }
}

questo viene compilato, cosa faccia non è ben chiaro nemmeno a me, figuriamoci a chi lo deve leggere..........

operazione "cattiveria quotidiana" eseguita, adesso stacco

int led=13;
int led1=12;
int stato;
int stato1;

void setup() {
Serial.begin(9600);
pinMode(led,OUTPUT);
pinMode(led1,OUTPUT);
pinMode(10, OUTPUT);
}

void loop() {


char stato; //definizione

void serialEvent() {
  while (Serial.available()) {
    stato = Serial.read();
    switch (stato) {
      case 'A':
        digitalWrite(led,HIGH);
        break;
      case 'S':
        digitalWrite(led,LOW);
        break;
    }
  }
}

è la tua versione, ho "eradicato" gli oggetti String, tratto un solo carattere alla volta, faccio la switch su una variabile char (che è intero, piccolo piccolo ma intero)
ma sopratutto il case riferisce a singolo carattere, vedi l'uso di apici - non stringhe (corte) vedi l'uso di virgolette
'A' e' un singolo carattere
"A" è un array di due caratteri, chiamato stringa di 'C', ecco l'origine della confusione
il primo carattere è 'A', il secondo è '\n' che vale zero, si potrebbe anche scrivere direttamente zero

Colgo la palla al balzo per spiegare qualcosa su serialEvent().

Questa funzione viene chiamata (non sempre) ad ogni ciclo di loop, più precisamente al termine della funzione loop().

Qui il codice da main.cpp

	setup();
    
	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}

Ora se andiamo a vedere cosa fa la funzione serialEventRun capiamo qualcosa in più.
La funzione in questione si trova in HardwareSerial.cpp qui un estratto:

void serialEventRun(void)
{
#if defined(HAVE_HWSERIAL0)
  if (Serial0_available && serialEvent && Serial0_available()) serialEvent();
#endif
#if defined(HAVE_HWSERIAL1)
  if (Serial1_available && serialEvent1 && Serial1_available()) serialEvent1();
#endif

Pare evidente che serialEvent() viene chiamata solo se la condizione seguente risulta vera:

Serial0_available && serialEvent0 && Serial0_available()

Ora la funzione Serial0_available() restituisce un bool e la posto per intero di seguito:

bool Serial0_available() {
  return Serial.available();
}

Quindi riassumendo serialEvent() viene chiamata solo se ci sono dati nel buffer, se il buffer è vuoto non viene chiamata.

Ora tutto questo il reference non lo mostra e mostra un uso che può essere frainteso, nel senso che l'esempio è fatto in modo da richiedere il while (Serial.available()) che non sempre è necessario.

Ad esempio non è necessario quando vogliamo leggere un carattere da seriale e subito dopo abbandonare la funzione serialEvent().

Nel caso richiesto da @fabiano2017 il while (Serial.available()) non è necessario, per cui il codice di @Standardoil diventa come segue:

void serialEvent() {
 
    stato = Serial.read();
    switch (stato) {
      case 'A':
        digitalWrite(led,HIGH);
        break;
      case 'S':
        digitalWrite(led,LOW);
        break;
    }

}

Inoltre se non ci sono dati nel buffer la Serial.read() restituisce -1.

Aggiungo che l'esempio nel reference non lo userei neanche se dovessi collezionare i caratteri e inserirli in un vettore, questo perché durante il tempo che colleziono i caratteri il codice dentro la loop() non viene eseguito.

Ciao.

Maurotec:
... Ora la funzione Serial0_available() restituisce un bool e la posto per intero di seguito:

bool Serial0_available() {

return Serial.available();
}

... che viola lo standard dei "bool" che vorrebbe, come unici valori ammessi, true e false (1 e 0), mentre, notoriamente, la Serial.available() NON ritorna un bool, ma ritorna un int che indica il numero di caratteri disponibili nel buffer.

Molto più pulita sarebbe stata (usando l'odiatissimo operatore ternario :grin:):

bool Serial0_available() {
  return ( Serial.available() ? true : false ) ;
}

... almeno ritornava veramente un bool :wink:

Insomma, una mezza schifezzuola quel pezzo di codice ...

Guglielmo

Ma la funzione serialEvent() dovrebbe essere messa FUORI dal loop.

void loop()
{
   LOOP
 }

void serialEvent()
{
  SERIALCHEFACCIAMO
}

Maurotec:
Aggiungo che l'esempio nel reference non lo userei neanche se dovessi collezionare i caratteri e inserirli in un vettore, questo perché durante il tempo che colleziono i caratteri il codice dentro la loop() non viene eseguito.

Ma d'altra parte se il codice nella loop è "lento" è il buffer di ricezione che si può riempire. È vero che durante il while per raccogliere i byte non viene eseguito altro (a parte gli interrupt), ma quel while di massimo 64 iterazioni è molto veloce. L'errore dell'esempio è piuttosto usare la classe String (che solo apparentemente semplifica il compito al principiante).