Controllare la scheda SX16-RF con la scheda FOXData di pubblicazione: 13-07-2005 | Versione Italiana | (No English Version) Parole chiave: - How-To - Linux - Schede Area SX - |
In quest'articolo vediamo come collegare ad una FOX board (http://www.acmesystems.it/) la scheda d'espansione INPUT/OUTPUT SX16 in configurazione stand alone prodotta da AreaSX S.r.l. (http://www.areasx.com) .
La FOX è una board di ridotte dimensioni (66 x 72 mm) basata su micro ETRAX LX100 MCM 4+16 prodotto da AXIS che racchiude al suo interno un sistema Linux embedded dotato di server WEB, FTP, SSH, TELNET ecc. La scheda FOX è programmabile in linguaggio C e i sorgenti realizzati possono essere compilati tramite apposito SDK, disponibile al momento solo per ambiente Linux, scaricabile gratuitamente dal sito AXIS all'URL: http://developer.axis.com/download/compiler/old/ o in alternativa usando WebCompiler alla pagina
http://www.acmesystems.it/?page=webcompiler.
Per maggiori informazioni sulla FOX e su come programmarla si consiglia di consultare il sito del produttore:
http://www.acmesystems.it/.
La SX16 è una scheda di espansione equipaggiata con 24 ingressi di cui:
8 ingressi diretti a livelli TTL (0V-5V)
8 ingressi filtrati (filtro CLC) a livelli TTL (0V-5V)
8 ingressi optiosolati a cui è possibile collegare tensioni fino a 24V CC, configurabili anche come ingressi TTL (0V-5V)
sei uscite a relè che consentono di operare tensioni fino a 125V (30W di carico) e un sensore di temperatura digitale DS1621.
La configurazione Stand Alone è caratterizzata dalla presenza, a bordo, di un microprocessore PIC già programmato con un firmware che semplifica notevolmente l'interfacciamento con un PC o un sistema capace di gestire una comunicazione seriale. Oltre al micro è presente anche un modulo RF modello ER400 che rende la SX16 completamente libera da fili (wireless) che la collegano al sistema che la controlla. L'ER400, prodotto dalla LPRS, è un completo sistema per incapsulare una comunicazione seriale bidirezionale su una portante in radiofrequenza di 433MHz e capace di coprire distanze, in condizioni ottimali, di 250mt.
Per consentire alla scheda FOX di comunicare via onde radio con la scheda SX16 dobbiamo collegare su una delle due porte USB di cui è dotata la FOX un modulo RF04.
RF04 è un modulo di ridotte dimensioni che integra un convertitore USB - Seriale della
FTDI (compatibile con il Kernel 2.4 e superiore) e un ER400 per trasmettere e ricevere il segnale segnale su portante a 433MHz.
Il riconoscimento del RF04 da parte del sistema Linux è immediato, il device è visibile ed accessibile alla directory /dev/ con il nome ttyUSB0.
Nei paragrafi che seguono oltre ad essere descritto il protocollo di comunicazione con la SX16 stand alone, viene fornito un semplice d'esempio scritto in C che può essere compilato usando l'utility WebCompiler. Il file .out che otterremo al termine della compilazione, potrà essere caricato nella memoria RAM o FLASH della FOX via FTP.
Per salvare il nostro programma in RAM, bisogna attraverso un Client FTP, collegarsi alla FOX Board per default all'IP 192.168.0.90, username root e password acme, e trasferire il file .out nella directory /var/state/ Questa posizione permette di provare i propri programmi ma appena viene tolta l'alimentazione alla scheda, i file caricati vengono cancellati. Per Salvare il nostro programma in FLASH, bisogna collegarsi in FTP come precedentemente visto e salvare il file .out nella directory /mnt/flash Per rendere eseguibile in programma bisogna modificare i permessi come segue:
chmod +x programma.out
a questo punto possiamo lanciare il nostro esempio precedendo al nome dell'eseguibile un "./"
./programma.out
Comandare i Relè della SX16
Il protocollo per attivare i relè della SX16, prevede l'invio di un comando composto da sei byte e ritorna altrettanti byte ad operazione eseguita, per indicare lo stato dei relè.
Nella tabella che segue viene descritto byte a byte il comando da inviare
Byte |
Descrizione |
Esadecimale |
1 |
START |
0x33 |
2 |
INDIRIZZO |
0x01 |
3 |
COMANDO |
0x03 |
4 |
RELE' |
da 0x01 a 0x06 |
5 |
STATO |
0x00 OFF - 0x01 ON |
6 |
ZERO |
0x00 |
Analisi dei byte che compongono la risposta inviata dalla SX16 al nostro PC ad operazione completata:
Byte |
Descrizione |
Esadecimale |
1 |
SOR |
0x22 |
2 |
INDIRIZZO |
0x01 |
3 |
COMANDO |
0x03 |
4 |
STATO RELE' |
da 0x00 a 0x63 |
5 |
ZERO |
0x00 |
6 |
ZERO |
0x00 |
Sorgente d'esempio in C:
#include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> #include <sys/types.h> #include <sys/stat.h> #include <signal.h> #include <stdlib.h>
#define BAUDRATE B19200 #define DEVICE "/dev/ttyUSB0" //COMUNCAZIONE CON SX16 #define START 0x33 #define RETURN_START 0x22 #define ADDR 0x01 #define WRITE_CMD 0x03 #define ALL_CMD 0xFF #define CH 0x01 #define ON 0x01 #define OFF 0x00 #define ZERO_CHAR 0x00
/////////////////////// //PROTOTIPI /////////////////////// int read_key(); int send2sx16 (int _fd, char *cmd2sx16, char *sx16return);
/////////////////////// //FUNZIONI /////////////////////// //Legge l'input da tastiera int read_key(){ int cmd; while ((cmd = getchar())!=0){ if (cmd!=10) break; } return cmd; } //Invia un comando alla SX16 int send2sx16 (int _fd, char *cmd2sx16, char *sx16return){ int res; if (write(_fd, cmd2sx16, 6) < 0) { //Invio sulla seriale fallito return 0; } else { //Invio del comando riuscito usleep(100000); //sleep per 100mSec res = read(_fd,sx16return,6); sx16return[res]=0; return 1; } }
//////////////////////////////// // // MAIN // //////////////////////////////// int main (int argc, char * argv[]) { int fd, res, i; int b; int line_rele; int state_rele; struct termios oldtio,newtio; char buf[7]; system("clear"); //Pulizia della console printf("----------------------------\n"); printf(" FOX 2 SX16\n\n"); printf(" Ver: 1.0\n"); printf(" Author: Daniele De Santis\n"); printf(" E-Mail: [email protected]\n\n"); printf(" Test RELE'\n"); printf("----------------------------\n"); printf("Apertua Porta COM\n"); fd = open(DEVICE, O_RDWR | O_NOCTTY); if (fd < 0 ) { printf("Device %s non pesente su questo sistema\n\n", DEVICE); exit(-1); } printf("Inizializzazione della comunicazione seriale\n"); tcgetattr(fd,&oldtio); /* Salva i precedenti settaggi */ bzero(&newtio, sizeof(newtio)); newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 6; tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); //Inizializzazione device seriale terminata printf("Seleziona il relè da settare [1 - 6]\n"); line_rele = read_key(); if(line_rele < 49 && line_rele > 54) line_rele=49; printf("Seleziona lo stato [1 ON - 0 OFF]\n"); state_rele = read_key(); if ((state_rele<48) || (state_rele > 49)) state_rele = 48; printf ("STATO %d\n", state_rele); //FORMATTO IL PACCHETTO DA MANDARE ALLA SERIALE buf[0]=0; buf[0]=START; buf[1]=ADDR; buf[2]=WRITE_CMD; buf[3]=(line_rele - 48); if(state_rele==49) buf[4]=ON; else buf[4]=OFF; buf[5]=ZERO_CHAR; res=send2sx16 (fd, buf, buf); if (res) { if((buf[0]==RETURN_START) && (buf[1]==ADDR) && (buf[2]==WRITE_CMD)) { printf("----------------------------\n"); printf(" STATO DEI RELE SULLA SX 16 \n"); printf("----------------------------\n"); res = buf[3]; for (i=0; i<6; i++){ b = res & 1; res >>=1; if(b){ printf("RELE' %d [X] ON\n", (i + 1) ); } else { printf("RELE' %d [ ] OFF\n", (i + 1)); } } } } printf("\nChiusura comunicazione seriale...\n"); tcsetattr(fd,TCSANOW,&oldtio); printf("Arrivederci :)\n"); close(fd); exit(0); }
Eseguendo il programma da una console a video avremo una schermata come quella che segue
dove sarà possibile selezionare il relè che si vuole settare da 1 a 6 e impostare il valore ON o OFF.A comando terminato a video avremo un lo stato di ogni singolo relè.
Lettura della temperatura:
Sulla SX16 è montato un sensore di temperatura di tipo digitale a 8bit della Dallas DS1621 con renge di lettura compreso tra -55 e + 128 con una precisione di 0.5 °C
Il comando da inviare per effettuare l'acquisizione della temperatura è il seguente:
Byte |
Descrizione |
Esadecimale |
1 |
START |
0x33 |
2 |
INDIRIZZO |
0x01 |
3 |
COMANDO |
0x02 |
4 |
ZERO |
0x00 |
5 |
ZERO |
0x00 |
6 |
ZERO |
0x00 |
La risposta che riceveremo dalla SX16 ad acquisizione terminata:
Byte |
Descrizione |
Esadecimale |
1 |
SOR |
0x22 |
2 |
INDIRIZZO |
0x01 |
3 |
COMANDO |
0x02 |
4 |
TEMPERATURA |
da 0x00 a 0xC9 |
5 |
TEMPERATURA |
0x00 o 0x80 |
6 |
ZERO |
0x00 |
il 4 byte rappresenta la parte intera del valore della temperatura ed è positivo per valori esadecimali che vanno da 0x00 fino a 0x80 superata questa soglia le letture della temperatura sono negative. Il quinto byte rappresenta il valore decimale della lettura è può avere solo due valori 0x00 che rappresenta ",0" o 0x80 che rappresenta il mezzo grado ",5".
Sorgente d'esempio in C:
#include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> #include <sys/types.h> #include <sys/stat.h> #include <signal.h> #include <stdlib.h>
#define BAUDRATE B19200 #define DEVICE "/dev/ttyUSB0" #define DELAY_LOOP 10 //In sec //COMUNCAZIONE CON SX16 #define START 0x33 #define RETURN_START 0x22 #define ADDR 0x01 #define WRITE_CMD 0x03 #define TMP_CMD 0x02 #define READ_CMD 0x01 #define ALL_CMD 0xFF #define CH 0x01 #define ON 0x01 #define OFF 0x00 #define ZERO_CHAR 0x00 #define TEST 0x80
/////////////////////// //PROTOTIPI /////////////////////// int send2sx16 (int _fd, char *cmd2sx16, char *sx16return);
//Invia un comando alla SX16 int send2sx16 (int _fd, char *cmd2sx16, char *sx16return){ int res; if (write(_fd, cmd2sx16, 6) < 0) { //Invio sulla seriale fallito return 0; } else { //Invio del comando riuscito usleep(500000); //sleep per 500mSec res = read(_fd,sx16return,6); return 1; } }
//////////////////////////////// // // MAIN // //////////////////////////////// int main (int argc, char * argv[]) { int fd, res; auto float temp; struct termios oldtio,newtio; unsigned char buf[20]; system("clear"); //Pulizia della console printf("Apertua Porta COM\n"); fd = open(DEVICE, O_RDWR | O_NOCTTY); if (fd < 0 ) { printf("Device %s non pesente su questo sistema\n\n", DEVICE); exit(-1); } printf("Inizializzazione della comunicazione seriale\n"); tcgetattr(fd,&oldtio); /* Salva i precedenti settaggi */ bzero(&newtio, sizeof(newtio)); newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 5; tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); //Inizializzazione device seriale terminata while (1){ system("clear"); //FORMATTO IL PACCHETTO DA MANDARE ALLA SERIALE buf[0]=0; buf[0]=START; buf[1]=ADDR; buf[2]=TMP_CMD; buf[3]=ZERO_CHAR; buf[4]=ZERO_CHAR; buf[5]=ZERO_CHAR; res=send2sx16 (fd, buf, buf); if (res) { if((buf[0]==RETURN_START) && (buf[1]==ADDR) && (buf[2]==TMP_CMD)) { printf("---------------------------------------\n"); printf(" FOX 2 SX16\n\n"); printf(" Ver: 1.0\n"); printf(" Author: Daniele De Santis\n"); printf(" E-Mail: [email protected]\n\n"); printf(" LETTURA DELLA TEMPERATURA DALLA SX 16 \n"); printf("---------------------------------------\n"); printf("Temperatura letta dal sensore DS1621: ");
temp=0; // Imposto il mezzo grado if (buf[4]==0x80) temp=0.5; if (buf[3] & 0x80) { // Temperatura negativa temp+=(!buf[3])+1; temp=-temp; } else { // Temperatura >0 temp+=buf[3]; } printf("%.2f °C\n", temp); } else { printf("ERRORE -Risposta dalla SX16 non valida\n"); } printf("\nCTRL+C per uscire\n"); usleep(1000000 * DELAY_LOOP); } else { printf("ERRORE -Comunicazione con il device %s fallito\n", DEVICE); exit(-1); } } printf("\nChiusura comunicazione seriale...\n"); tcsetattr(fd,TCSANOW,&oldtio); printf("Arrivederci :)\n"); close(fd); exit(0); }
eseguendo il programma avremo una videata come quella che segue
Acquisizione dello stato dai 24 ingressi:
I 24 ingressi sono divisi a blocchi di otto ed ognuno di questi è caratterizzato da una tipologia d'ingresso specifica. I primi otto (punto 1 nella foto che segue) sono di tipo optoisolato, ideali per collegare segnali elettrici con tensioni superiori ai 5V fino ad un massimo di 24V. Il secondo blocco (punto 2 nella foto che segue) è composto da ingressi di tipo TTL a su cui è possibile applicare livelli di tensione compresi tra 0V e massimo 5V. Il terzo blocco (punto 3) è identico per quanto riguarda i livelli di tensione al secondo blocco con la sola differenza che su ogni linea è presente un filtro antidisturbo del tipo CLC.
La lettura dei 24 ingressi viene effettuata con un unico comando il cui protocollo è descritto nella tabella che segue:
Byte |
Descrizione |
Esadecimale |
1 |
START |
0x33 |
2 |
INDIRIZZO |
0x01 |
3 |
COMANDO |
0x01 |
4 |
ZERO |
0x00 |
5 |
ZERO |
0x00 |
6 |
ZERO |
0x00 |
come risposta dalla SX16 si avrà un pacchetto, sempre di sei byte, rispettante il seguente protocollo:
Byte |
Descrizione |
Esadecimale |
1 |
SOR |
0x22 |
2 |
INDIRIZZO |
0x01 |
3 |
COMANDO |
0x01 |
4 |
INPUT CTC |
da 0x00 a 0xFF |
5 |
INPUT TTL |
da 0x00 a 0xFF |
6 |
INPUT OPT |
da 0x00 a 0xFF |
Sorgente d'esempio in C:
#include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> #include <sys/types.h> #include <sys/stat.h> #include <signal.h> #include <stdlib.h>
#define BAUDRATE B19200 #define DEVICE "/dev/ttyUSB0" #define DELAY_LOOP 10 //In sec //COMUNCAZIONE CON SX16 #define START 0x33 #define RETURN_START 0x22 #define ADDR 0x01 #define WRITE_CMD 0x03 #define READ_CMD 0x01 #define ALL_CMD 0xFF #define CH 0x01 #define ON 0x01 #define OFF 0x00 #define ZERO_CHAR 0x00
/////////////////////// //PROTOTIPI /////////////////////// int send2sx16 (int _fd, char *cmd2sx16, char *sx16return);
//Invia un comando alla SX16 int send2sx16 (int _fd, char *cmd2sx16, char *sx16return){ int res; if (write(_fd, cmd2sx16, 6) < 0) { //Invio sulla seriale fallito return 0; } else { //Invio del comando riuscito usleep(100000); //sleep per 100mSec res = read(_fd,sx16return,6); sx16return[res]=0; return 1; } }
//////////////////////////////// // // MAIN // //////////////////////////////// int main (int argc, char * argv[]) { int fd, res, i; int b; struct termios oldtio,newtio; char buf[7]; system("clear"); //Pulizia della console printf("Apertua Porta COM\n"); fd = open(DEVICE, O_RDWR | O_NOCTTY); if (fd < 0 ) { printf("Device %s non pesente su questo sistema\n\n", DEVICE); exit(-1); } printf("Inizializzazione della comunicazione seriale\n"); tcgetattr(fd,&oldtio); /* Salva i precedenti settaggi */ bzero(&newtio, sizeof(newtio)); newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; newtio.c_lflag = 0; newtio.c_cc[VTIME] = 0; newtio.c_cc[VMIN] = 6; tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); //Inizializzazione device seriale terminata while (1){ system("clear"); //FORMATTO IL PACCHETTO DA MANDARE ALLA SERIALE buf[0]=0; buf[0]=START; buf[1]=ADDR; buf[2]=READ_CMD; buf[3]=ZERO_CHAR; buf[4]=ZERO_CHAR; buf[5]=ZERO_CHAR; res=send2sx16 (fd, buf, buf); if (res) { if((buf[0]==RETURN_START) && (buf[1]==ADDR) && (buf[2]==READ_CMD)) { printf("---------------------------------------\n"); printf(" FOX 2 SX16\n\n"); printf(" Ver: 1.0\n"); printf(" Author: Daniele De Santis\n"); printf(" E-Mail: [email protected]\n\n"); printf(" STATO DELLE LINEE D'INPUT SULLA SX 16 \n"); printf("---------------------------------------\n");
printf("Stato degli ingressi CLC:\n"); for (i=0; i<=7; i++){ b = buf[3] & 1; buf[3] >>=1; if(b) printf("LINEA CLC %d [X] ON\n", (i + 1) ); else printf("LINEA CLC %d [ ] OFF\n", (i + 1)); } printf("Stato degli ingressi TTL:\n"); for (i=0; i<=7; i++){ b = buf[4] & 1; buf[4] >>=1; if(b) printf("LINEA TTL %d [X] ON\n", (i + 1) ); else printf("LINEA TTL %d [ ] OFF\n", (i + 1)); } printf("Stato degli ingressi OPTOISOLATE:\n"); for (i=0; i<=7; i++){ b = buf[5] & 1; buf[5] >>=1; if(b) printf("LINEA OPTO %d [X] ON\n", (i + 1) ); else printf("LINEA OPTO %d [ ] OFF\n", (i + 1)); } } else { printf("ERRORE -Risposta dalla SX16 non valida\n"); } printf("\nCTRL+C per uscire\n"); usleep(1000000 * DELAY_LOOP); } else { printf("ERRORE -Comunicazione con il device %s fallito\n", DEVICE); exit(-1); } } printf("\nChiusura comunicazione seriale...\n"); tcsetattr(fd,TCSANOW,&oldtio); printf("Arrivederci :)\n"); close(fd); exit(0); }
Sulla console, lanciando il programma, apparirà una videata come a quella che segue
Per ogni sorgente è possibile modificare il device di lettura cambiando il valore #define DEVICE "/dev/ttyUSB0"
Segnala questo articolo:
Parole chiave: - How-To - Linux - Schede Area SX -
|