Danke für den Tip!
Im Prinzip wohl schon. Allerdings möchte ich LCD4Linux nutzen und das LCD soll auch an andere Geräte wie z.B. das NAS angeschlossen werden können.
Druckbare Version
Danke für den Tip!
Im Prinzip wohl schon. Allerdings möchte ich LCD4Linux nutzen und das LCD soll auch an andere Geräte wie z.B. das NAS angeschlossen werden können.
Hallo,
ein sehr gelungenes Projekt und mein erster tieferer Kontakt mit dem Raspberry Pi. Ich hab mir gleich den MPD installiert und mal losgelegt. Jetzt habe ich ein WWW Radio für meine Stereoanalage, welchen ich nicht ganz so elegant nur mit dem Smartphone steuere.
Ich bin gerade dabei eine Anbindung an mein Autoradio zu basteln. Da ich auch den MPD dafür benutzen will und die originalen Radiotasten zum steuern haben will, habe ich eine Frage zum "empfangen" Code.
Ich habe leider eine etwas komplexere Schnittstelle mit Umsetzer von 1-Draht Bus auf RS232. Ich bekomme die Daten schon mal ins Board rein mit einem etwas angepassten "empfangen.c", wo ich schon mal heilfroh bin.
Senden geht auch schon zumindest über Shell.
Leider kommen immer mehrere Zeichen auf einmal an und dann ist kurzzeitig wieder Ruhe auf der Schnittstelle.
Ein Beispiel in Hex
ungefähr so
18 04 FF 02 00 E1
0.1s Pause
18 04 FF 02 00 E1
2s Pause
FF FF FF FF FF FF (irgendein Code)
Pause
etc.
Als Kommunikation habe ich 9600,8e,1
Gibt es eine Möglichkeit mit der im Code verwendeten UART Kommunikation über einen Status zu erkennen wann ein Datensatz übertragen wurde bzw. gerade kein neues Zeichen am UART ankommt? Wenn das geht konnte ich die Zeichen immer sauber auslesen, da sich ja nicht kontinuierlich gesendet werden sondern Paketweise.
Ich habe auch schon versucht über einen aus meinem Chip ausgegeben Sendungsstatus (via wiringPi) ans Ziel zu kommen. Doch ist das leider zu ungenau und es werden immer weider Zeichen verschluckt. Heißt entweder werden die GPIOs zu langsam erkannt oder der Chip ist hier ungenau.
Über einen kleinen Anstoß meiner Grüzkiste wäre ich sehr froh.
Viele Grüße
Rainer
Könntest ja blockweise a 6 Byte lesen in dem du beim read eine Struktur/einen Array und als maximale Größe 6 (bzw die Größe der Struktur/des Arrays) übergibst.
Wenn alle Bytes 0xFF sind definierst du dann, dass die Übertragung vorbei ist.
Danke ePyx für deine Antwort. Blockweise auslesen kann ich leider nicht machen, da die Bytelänge und die Ruhezeiten variieren. Ich hätte gestern schon einen Datenmitschnitt posten sollen, damit es klarer wird. Abschlusszeichen ala CR hab ich auch nicht. Der letzte Wert ist zwar immer die XOR Checksumme von den empfangenen Bytes pro Block, welche man zur Plausibilitätsprüfung heranziehen kann, doch weiß ich nicht wie man das während des empfangens schon verwerten soll.
Code:2013-01-14 06:41:53.390 18 04 FF 02 00 E1
2013-01-14 06:41:53.390 76 0C 68 39 00 82 00 10 00 05 01 00 01 BC
2013-01-14 06:41:53.405 68 04 FF 3B 00 A8
2013-01-14 06:41:53.421 68 05 18 38 01 00 4C
2013-01-14 06:41:53.421 68 10 C0 23 41 30 00 20 20 20 20 20 20 20 20 20 20 EA
2013-01-14 06:41:53.436 C8 05 80 23 42 20 0C
2013-01-14 06:41:53.436 18 0A 68 39 00 02 00 10 00 05 01 55
2013-01-14 06:41:53.670 68 04 BF 02 01 D0
2013-01-14 06:41:53.686 68 05 80 41 01 01 AC
2013-01-14 06:41:53.780 68 03 D0 5D E6
2013-01-14 06:41:57.290 18 04 FF 02 00 E1
2013-01-14 06:42:01.174 18 04 FF 02 00 E1
2013-01-14 06:42:02.843 68 05 18 38 03 00 4E
2013-01-14 06:42:02.874 18 0A 68 39 02 09 00 10 00 05 01 5C
2013-01-14 06:42:02.968 68 03 18 01 72
2013-01-14 06:42:03.015 18 04 FF 02 00 E1
2013-01-14 06:42:03.108 18 0A 68 39 02 09 00 10 00 05 15 48
2013-01-14 06:42:03.826 18 0A 68 39 09 09 00 10 00 08 99 C2
2013-01-14 06:42:05.417 18 04 FF 02 00 E1
2013-01-14 06:42:06.977 68 05 18 38 01 00 4C
2013-01-14 06:42:06.993 C8 05 80 23 42 20 0C
2013-01-14 06:42:07.040 68 10 C0 23 41 30 00 20 20 20 20 20 20 20 20 20 20 EA
2013-01-14 06:42:07.040 C8 05 80 23 42 20 0C
2013-01-14 06:42:07.055 18 0A 68 39 00 02 00 10 00 08 99 C0
2013-01-14 06:42:09.676 18 04 FF 02 00 E1
Hast du dort irgendwelche Events ausgelöst? Also Tasten gedrückt oder so? Ein wenig Redundanz ist ja schon enthalten : Die Sequenzen 18 04 FF 02 00 E1, 68 05 18 38 01 00 4C und 68 10 C0 23 41 30 00 20 20 20 20 20 20 20 20 20 20 EA tauchen ja schon öfter auf.
Würde halt gucken was sich bei einem Tastendruck oder einer anderen Einstellung bei den gesendeten Daten ändert und das Protokoll weiter analysieren.
Hallo,da Linux ein Time sharing System ist, kann es zu diesen Pausen kommen. Du kannst versuchen, die Priorität deines Programmes zu erhöhen.Mit "nice -n15 Deinprogramm" starten, oder bei laufendem Programm mit "renice -n15 Deinprogramm".Vielleicht hilft das etwas.
Danke für eure Antworten.
das Timing wann die Blöcke kommen ist nicht kritisch. Sie werden alle vom RasPi erkannt.
Die Events kommen von den Steuergeräten auf dem Bus, heißt dem Radio und dem CD-Wechsler Emulator.
Das passt. Das einzige was ich im Moment noch nicht hinbekomme ist, das "empfangen.c" so anzupassen, dass wenn ein Block übertragen ist, dass heiß Ruhe auf dem Bus einkehrt die Daten auszulesen und in einen String zu schreiben.
Es müsste doch irgendwie möglich sein das der UART vom Raspberry merkt, wann ein Zeichen ankommt und wann kein Zeichen mehr ankommt und dementsprechend einen Status setzt. Wenn dieser Status auf 1 geht und dann wieder auf 0 ist der Block übertragen und damit kann man dann einen String bauen. Diesen Datensatz kann man dann auswerten.
Viele Grüße
Rainer
Kannst du mal bitte den Quellcode für die Parametrisierung des tty-Devices und für das Empfangen posten?
Mich interessiert dabei eigentlich mehr wie du den filedescriptor erstellst und wie du die Daten einliest. Ob du SIGIO etc benutzt oder ob du nur pollst etc.
Hab im Moment eigentlich noch einen fast unverändertes empfangen.c. Habe nur ein paar Änderungen an der Konfiguration der UART Schnittstelle gemacht. Und das beste ist, ich weiß nicht mal ob ich polle, da ich die Config des UART noch nicht gerafft hab und leider auch kein super C-Programmierer bin. Also verzeiht bitte meine Unwissenheit.
Den Rest des Codes und den Aufbau von peterfido habe ich mittlerweile verstanden. Von Zeile 45 bis 210 passiert erstmal nichts für mich interessantes, da dort ja nur die empfangenen Zeichen vom Atmel interpretiert werden. Das muss ich sowieso komplett umschreiben, da ich andere Codes verwende.
Ich hab folgendes geändert:
Die UART configuration also 9600,8e,1 und ein paar Dinge damit ich was auf dem Bildschirm zu sehen bekomme. Derzeit wird immer nur ein Zeichen abgeholt, was auf jeden fall noch geändert werden muss.
Wenn ich den Code richtig interpretiere lässt das Ding den UART komplett offen, da er in der while Schleife bleibt und der fd(close) danach kommt. Mhm...
Ziel ist wie im vorigen Beitrag beschrieben irgendwie hinzubekommen, dass die Blöcke erkannt werden und das in einem Puffer (255 Zeichen) abgeholt werden können. Den String für den Puffer könnte ich ja dann in der receive Funktion mittels schleife zusammenbauen und zurückgeben oder in eine globale Variable schreiben.
Nur leider stehe ich da im Moment einfach etwas auf dem Schlauch, weil ich nicht ganz verstehe was in der int init() Funktion passiert.
Grüße RainerCode:gcc -o empfangen_gpio_wiring -l rt empfangen_gpio_wiring.c -lwiringPi
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
//WiringPi include für SEN/STA Erkennung
#include <wiringPi.h>
#include <stdio.h>
//Konfig RASPI USART
#define BAUDRATE B9600 // 9600 Baud definieren für 8E1 I-Bus
char MODEMDEVICE[]= "/dev/ttyAMA0"; // Schnittstelle
int getit; //Nachrichtenblock angekommen
/*
Sx x=0 aktuellen Sender neu abspielen Nach Stop oder zum neu puffern, x>49 Sender x-48 abspielen
Bx x=0 abspielen stoppen, x=1 mpd neu starten
Px x=0 einen Senderplatz zurück x=1 einen Senderplatz hoch
Tx Taste x am Gerät gedrückt
resetreset Reboot des Raspi
*/
char eingang[255]="";
char d[1]="";
int anzahl=0;
int laenge=0;
int logg=0;
int fd; // File descriptor
int sender;
int lautst=95;
long int time_back;
long int time_ok;
struct termios newtio={};
unsigned char eingangleer() //Eingangstring leeren
{
int i;
for(i=0; i < laenge; i++){
eingang[i] = 0;
}
laenge=0;
}
unsigned char platzlautsenden() //Lautstärke und Senderplatz auf den kleinen Zahlen ausgeben
{ //Lautstärke 100% und Senderplatz 3 wird zu 100:03
char nummer[3];
int i=0;
char befehl[255]="";
sprintf(nummer,"%d",lautst);
strcpy(befehl,"/var/scripte/senden 2");
if (strlen(nummer)<3){
strcat(befehl,"0");
}
if (strlen(nummer)<2){
strcat(befehl,"0");
}
strcat(befehl,nummer);
strcat(befehl,":");
i=sender;
if(i>99){ //Die Anzeige ist 2-Stellig
i=99;
}
sprintf(nummer,"%d",i);
if (strlen(nummer)<2){
strcat(befehl,"0");
}
strcat(befehl,nummer);
system(befehl);
}
unsigned char radioein() //gewählten Platz in der Playlist abspielen
{
char nummer[3];
char befehl[255]="";
sprintf(nummer,"%d",sender);
strcpy(befehl,"mpc -q play ");
strcat(befehl,nummer);
system(befehl);
platzlautsenden();
}
unsigned char initmpd() //Schnittstelle parametrieren und öffnen
{
char befehl[30]="";
char s[2]="";
lautst=95;
system("/var/scripte/radio2.sh"); //InitScript für mpd
sleep(1);
system("mpc playlist > /tmp/mpdlist"); //Playlist zwischenspeichern
sleep(1);
FILE *f;
char Text[300]="";
char Text1[70]="";
char Text2[7]="volume";
f = fopen("/tmp/mpdlist","r");
anzahl=0; //Anzahl Einträge der Senderliste zählen
if(f!=NULL){
fgets(Text, sizeof(Text), f);
if(strlen(Text)<2){
fclose(f);
return;
}else{
anzahl=1;
while( fgets(Text, sizeof(Text), f) !=0 ){
if(strlen(Text)>2){
anzahl++;
}
if(anzahl>199){ //Nicht mehr wie 200
break;
}
}
}
fclose(f);
}
strcpy(befehl,"/var/scripte/senden 6"); //kleine Symbole im Display anzeigen lassen
s[0]=208; //Antennensymbol + FM anzeigen, als Zeichen für Bereit
strcat(befehl,s);
system(befehl);
strcpy(befehl,"/var/scripte/senden 7");
s[0]=130; //Stereo anzeigen
strcat(befehl,s);
system(befehl);
}
unsigned char abspielen() //Wiedergabe fortsetzen. Ist noch nichts abgespielt worden, Platz 1 abspielen
{
if (anzahl>0){
if (sender==0){
sender=1;
}else{ if(sender>anzahl){
sender=anzahl;
}
radioein();
}
}
}
unsigned char platzplus() //Senderplatz um 1 erhöhen
{ //Bei weniger Sendern in Liste auf Platz 1 zurück
if (anzahl>0){
sender++;
if (sender>anzahl){
sender=1;
}
radioein();
}
}
unsigned char platzminus() //Senderplatz um 1 verringern
{ //Bei 0 auf letzten Platz springen
if (anzahl>0){
sender--;
if (sender<1){
sender=anzahl;
}
radioein();
}
}
unsigned char lautsetzen() //Lautstärke einstellen
{
char nummer[3];
char befehl[255]="";
sprintf(nummer,"%d",lautst);
strcpy(befehl,"mpc -q volume ");
strcat(befehl,nummer);
system(befehl);
platzlautsenden();
}
unsigned char lauter() //Senderplatz um 5 Prozentpunkte erhöhen
{
if (lautst<96){
lautst+=5;
lautsetzen();
}
}
unsigned char leiser() //Senderplatz um 5 Prozentpunkte verringern
{
if (lautst>5){
lautst-=5;
}else{
lautst=0;
}
lautsetzen();
}
unsigned char radioaus() //Wiedergabe anhalten
{
system("mpc -q stop");
system("/var/scripte/senden 45");
sleep(1);
}
unsigned char auswerten() //Angekommene Daten auswerten
{ int i;
int fd1;
int zeile;
char ret;
char farbe[6]="";
/* Zum Schreiben öffnen */
if ((strcmp(eingang,"resetreset") ==0 )){
system("reboot");
}
if (eingang[0] == 83){ // S
zeile=eingang[1]-48; //Werte von 48-255 = 207 mögliche Sender, wird auf 200 limitiert
if (zeile == 0){ // bei 0 einfach weiter abspielen oder Platz 1 beginnen
abspielen();
}else if (zeile<=anzahl){
sender=zeile;
radioein();
}
}
if (eingang[0] == 84){ // T
if (eingang[1]>49&&eingang[1]<57){ //Wert soweit OK, Taste 1 = Powertaste und wird vom AVR ausgewertet
if (eingang[1]==50){ //2 - OK Taste
abspielen();
}
if (eingang[1]==51){ //3 - Wippe rechts
lauter();
}
if (eingang[1]==52){ //4 - BACK Taste
radioaus();
}
if (eingang[1]==53){ //5 - Menü Taste
system("/var/scripte/senden");
}
if (eingang[1]==54){ //6 - Wippe hoch
platzplus();
}
if (eingang[1]==55){ //7 - Wippe links
leiser();
}
if (eingang[1]==56){ //8 - Wippe runter
platzminus();
}
}
}
if (eingang[0] == 80){ // P
if (eingang[1]==49){ //1
platzplus();
}else{
platzminus();
}
}
if (eingang[0] == 66){ // B
if (eingang[1]==48){ //0 Wiedergabe stoppen
radioaus();
}
if (eingang[1]==49){ //1 mpd zurücksetzen
initmpd();
}
}
eingangleer();
}
unsigned char receive() //Zeichen empfangen
{
int res;
unsigned char buffer;
res = read(fd, &buffer, 1);
getit = fd;
return buffer;
}
int init() //Schnittstelle parametrieren und öffnen für I-Bus 9600 8E1
{
//O_RDONLY, O_WRONLY or O_RDWR -
//O_NDELAY (geht weiter, wenn keine Daten da sind und gibt "-1" zurueck)
// man 2 open fuer mehr Infos - see "man 2 open" for more info
// O_NOCTTY No ControllTeleType
fd = open(MODEMDEVICE, O_RDONLY | O_NOCTTY );
if (fd < 0){
printf("Fehler beim oeffnen von %s\n", MODEMDEVICE);
exit(-1);
}
memset(&newtio, 0, sizeof(newtio));
newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD | PARENB; //setzt die neuen Porteinstellungen
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0; /* set input mode (non-canonical, no echo, ...) */
newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
newtio.c_cc[VMIN] = 1; /* blocking read until 1 chars received old 1 */
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
//getit = O_NDELAY;
return fd;
}
int main(int argc, char** argv) //Programmstart
{
//new
int pin = 7; //GPIO 4
int value = 0; // Deklaration Eingangswert GPIO4
getit = 0;
printf ("Raspberry Pi wiringPi test program\n") ;
if (wiringPiSetup () == -1)
exit (1) ;
//new end Check wiring pi
pinMode(pin,INPUT);
char c;
init(); //Schnittstelle UART parametrieren und öffnen
sleep(5); //warten bis mpd gestartet ist
initmpd(); //mpd auf definierten Zustand bringen
while (1)
{
value = digitalRead (pin);
printf("Status Schnittstelle %d \n", getit );
//printf("SEN/STA: %d\n", value); // BUSRUHE?
c=receive();
//if((value==1)){
printf("MESSAGE %X\n", c); // c in Hex ausgeben %d = Dezimal %H = Hex
//}
/*
c=receive(); //Zeichen holen
if((c==13)){ //CR als Abschluß einer Zeile
auswerten();
}else if(c>13&&c<128){ //Alles von ASCii 14 bis 127 wird akzetpiert
eingang[laenge]=c;
laenge++;
if (laenge >254){ //Bei 254 Zeichen im Puffer wird automatisch ausgewertet
auswerten();
}
}
printf("The answer is %X\n", c); // c in Hex ausgeben %d = Dezimal %H = Hex
*/
}
close (fd);
return 0;
}
Der Code sieht sehr nach zusammen kopiert und entsprechend erweitert aus. Was schon recht doof ist, der bei termios der aktuelle Zustand des Terminals nicht gespeichert, sondern einfach überschrieben wird.
Das TTY-Device kann man als O_NONBLOCK deklarieren. Um zu erkennen ob Bytes im Puffer der seriellen Schnittstelle sind, kann man Signale benutzen. Das einfachste wäre das SIGIO-Signal, welches aufgerufen wird, sobald Daten eintreffen. Eine andere Möglichkeit um zu Prüfen ob Daten verfügbar sind ist :
Wobei das kein komplettes Beispiel ist, daher sollte man sich die manpages ansehen.Code:
int bytes_avaiable;ioctl(serial_file_descriptor, FIONREAD, &bytes_available);
PS : Das Ausführen der Befehle mit System kann im Übrigen hunds-gefährlich werden, da sollte man eher einen bestehenden Prozess forken.