Go Down

Topic: [C] Inviare dati ad Arduino (Read 2014 times) previous topic - next topic

arduinopro44

Ciao a tutti,
pensavo di non aver problemi con la parte relativa alla programmazione di Arduino ma sto avendo qualche difficoltà.


Sto provando un semplice programma che invia un intero ad Arduino ed in base al valore Arduino attiva un pin (relè).

Il codice del programma in C è il seguente:
Code: [Select]

char serialPort[] = "COM8";

int main(){
    FILE *porta;
    porta = fopen(serialPort,"w");  //Opening device file
if(porta == NULL){
printf("\nErrore");
abort();
}
     fprintf(porta,"%d",1);
     fclose(porta);
}




E lo sketch in Arduino è il seguente:
Code: [Select]

#define rele1 1

void setup() {
    Serial.begin(9600);
    pinMode(rele1,OUTPUT);
    digitalWrite(rele1,HIGH);
 }

int input;

void loop() {
    if(Serial.available()>0){
       input=Serial.read();
       if(input==1){
         digitalWrite(rele1,LOW);
         delay(1500);
         digitalWrite(rele1,HIGH);
       }
     }
}


Non capisco cosa mi sfugge.


Grazie in anticipo a chiunque voglia aiutarmi!

busco

if(Serial.available()>0){
       input=Serial.read();
       if(input==1){

Devi convertire input in numerico:

      input=Serial.read();
      input-=48;
      if(input==1){

arduinopro44

Non va nemmeno. Ricevo un valore molto alto, compreso da 200 e 1000: se faccio if(input>200) si attiva il pin.

Cos'altro sbaglio?

ExperimentUno

Il valore trasmesso in che formato è ?
ASCII, BYTE, WORD, FLOAT ?

arduinopro44

Il valore trasmesso in che formato è ?
ASCII, BYTE, WORD, FLOAT ?
Nel codice che ho postato qui invio un int (%d), ho provato ad inviare anche un char o una stringa. Ma mi da sempre problemi.

uwefed

Presumo che hai un Arduino UNO.

L'errore é nella prima riga:
"#define rele1 1"
Il pin 0 e 1 sono usati dalla seriale.

Usa un altro pin per il relá.
Ciao Uwe

arduinopro44

Presumo che hai un Arduino UNO.

L'errore é nella prima riga:
"#define rele1 1"
Il pin 0 e 1 sono usati dalla seriale.

Usa un altro pin per il relá.
Ciao Uwe
Si, ho un Arduino (Genuino) UNO Rev3.
Però in realtà utilizzo i ping digitali dal 2 in poi (quel #define rele1 1 l'ho aggiunto dopo aver copiato il codice solo per completezza e non ho fatto caso al fatto che appunto quel pin non lo utilizzavo).

Comunque non funziona proprio. Se dal monitor seriale invio il valore, invece, funziona. Quindi evidentemente è un problema nella parte del codice in C oppure nella "conversione" del valore che riceve Arduino.
Qualcuno ha quelle due righe di codice che permettono di far ciò che funzionino? Ho cercato ovunque ma non trovo nulla di diverso da ciò che ho fatto.

Grazie!

SukkoPera

Ma siamo sicuri che su Windows la porta seriale si possa usare come se fosse un file? A me pare proprio di no, quella è una prerogativa dei sistemi Unix e Unix-like! Secondo me se cerchi ti trovi da qualche parte un file che si chiama COM8 con dentro dei numeri :).
"Code is read much more often than it is written, so plan accordingly. Design for readability."

Guida rapida a ESP8266: https://goo.gl/kzh62E

arduinopro44

Ma siamo sicuri che su Windows la porta seriale si possa usare come se fosse un file? A me pare proprio di no, quella è una prerogativa dei sistemi Unix e Unix-like! Secondo me se cerchi ti trovi da qualche parte un file che si chiama COM8 con dentro dei numeri :).
Si come ho scritto ho anch'io dei dubbi sulla parte in C. Però il collegamento avviene ed invio dei dati: mettendo un else dopo quell'if la scheda risponde.
Nessuno ha mai inviato un intero ad una scheda Arduino utilizzando Windows (e magari C, ma va bene anche C++) ?

SukkoPera

 Che compilatore stai usando?

Se lo invia, dall'altra parte ti arriva una stringa, e devi quindi convertire in intero come dice busco (anche se io userei l'apposita funzione atoi()). In alternativa prova a scrivere con fwrite().
"Code is read much more often than it is written, so plan accordingly. Design for readability."

Guida rapida a ESP8266: https://goo.gl/kzh62E

arduinopro44

Che compilatore stai usando?

Se lo invia, dall'altra parte ti arriva una stringa, e devi quindi convertire in intero come dice busco (anche se io userei l'apposita funzione atoi()). In alternativa prova a scrivere con fwrite().
Utilizzo Visual Studio.
Comunque ho provato anche con fwrite ma non funziona. Ho provato a convertire il valore ma non funziona nemmeno (anche perché non capisco che valore arrivi, dato che non posso usare contemporaneamente il monitor seriale e la console).

nid69ita

#11
Dec 29, 2016, 11:41 am Last Edit: Dec 29, 2016, 11:46 am by nid69ita
Un pò di debug.
1. per provare solo la parte Arduino basta che i dati li spedisci da Serial Monitor di Arduino IDE
Logicamente come già detto quello che spedisci sono numeri ma in testo, quindi non spedisci 1  ma '1' come carattere quindi 48 come valore del byte

2. poi aggiungi nel codice Arduino un bel Serial.println()   del dato che ricevi  ovvero input, per capire cosa sta spedendo.

3. non saprei se da C con quei semplici comandi ha una velocità della porta (baude rate) fissata a 9600.
mi pare che quei parametri manchino.
a)Questo esempio ma in C.NET usa la classe serialport che ha il settaggio della velocità
http://www.instructables.com/id/Serial-Port-Programming-With-NET/
b)Qui un esempio in C puro usando seriale come file, ma sotto windows usa l'API di windows per poter settare i parametri:
http://stackoverflow.com/questions/11765349/interacting-with-a-serial-port-using-the-c-functions-fopen-fread-and-fwrite
my name is IGOR, not AIGOR

astrobeed

Ma siamo sicuri che su Windows la porta seriale si possa usare come se fosse un file?
Assolutamente si, in C la porta seriale è un file indipendentemente dal sistema operativo, poi è il compilatore che gestisce la cosa a livello hardware e software in base al s.o.

Scientia potentia est

dally

#13
Dec 29, 2016, 01:47 pm Last Edit: Dec 29, 2016, 02:00 pm by dally
Assolutamente si, in C la porta seriale è un file indipendentemente dal sistema operativo
*dipende*

In Borland TurboC (ma anche Microsoft C) sotto DOS la gestisce delle seriali l'hanno proposta in almeno  due modi.

C'e' una primitiva nelle librerie a corredo scritte da Borland che richiamano delle subroutine del BIOS, il tutto poi mascherato da stdio (standard I/O,  definito da #include <stdio.h>), quindi vedi

Code: [Select]


       int fgetc(FILE *stream);
       int fputc(int c, FILE *stream);


tipico approccio a stream usato anche a UNIX.

Pero' spesso de-facto in tanti e tanti listati pubblicati sulle riviste o codice di alcuni progetti (tra cui App.!PC per Gemini-II, guest-x86 card Acorn, lato support DOS) sono state usate librerie che accedono direttamente all'hw, ai tipici indirizzi dove sono mappate le prime quattro porte seriali previste dal progetto Personal Computer IBM

COM1 0x3F8
COM2 0x2F8
COM3 0x3E8
COM4 0x2E8

PORT1 e' l'address della porta seriale scelta tra le 4 qui sopra

Code: [Select]

/* Communication Settings */
outportb(PORT1 + 3 , 0x80); /* SET DLAB ON */
outportb(PORT1 + 0 , 0x03); /* Set Baud rate - Divisor Latch Low Byte */

/* 0x01 = 115,200 BPS */
/* 0x02 = 57,600 BPS */
/* 0x03 = 38,400 BPS */
/* 0x06 = 19,200 BPS */
/* 0x0C = 9,600 BPS */
/* 0x18 = 4,800 BPS */
/* 0x30 = 2,400 BPS */

outportb(PORT1 + 1 , 0x00); /* Set Baud rate - Divisor Latch High Byte */
outportb(PORT1 + 3 , 0x03); /* 8 Bits, No Parity, 1 Stop Bit */
outportb(PORT1 + 2 , 0xC7); /* FIFO Control Register */
outportb(PORT1 + 4 , 0x0B); /* Turn on DTR, RTS, and OUT2 */


Segue l'I/O vero e proprio. Periferiche mappate in spazio I/O. Questa cosa (per certi versi una schifezza) e' tipica dei PC, a sua volta eredita' degli Z80 ed 8080, quest'ultimo bis bis nonno degli attuali x86. Le macchine RISC non e' detto che possano farlo, a volte non lo fanno proprio perche' tutto e' mappato in spazio ram, lineare e pulito. I PC hanno invece un secondo spazio fisico dedicato alle periferiche, difatti TurboC sotto DOS usa le port.byte functions.

Code: [Select]

ch = inportb(PORT1); /* Get Char from the Serial Port */
...
outportb(PORT1, ch);} /* Send Char to Serial Port */


Insomma questo codice-approccio-B non e' portabile, credo funzioni solo sotto DOS e non oltre windows98. E' un de-facto solo perche' largamente usato e diffuso in rete negli anni 90 e primi del 2000, ma decisamente non e' la strada pulita di gestire le seriali.

Conclusione

Fai stra-bene a tagliare corto verso la soluzione piu' pulita e portabile possibile :D

SukkoPera

Infatti "Indipendentemente dal sistema operativo" mi sembra un po' troppo ottimistico, comunque se su Windows/Visual Studio è così, tanto meglio.
"Code is read much more often than it is written, so plan accordingly. Design for readability."

Guida rapida a ESP8266: https://goo.gl/kzh62E

Go Up