PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RP6Control M32: Projekt I2C-Slave



Dirk
11.09.2012, 15:47
Hallo Leute,

hier mache ich mal einen Thread auf, in dem wir einen I2C-Slave für die M32-Platine entwickeln können.

Erst mal die Planung:

1. Der I2C-Slave für die M32 soll genauso arbeiten, wie der RP6Base I2C-Slave (RP6Base_I2CSlave.c) in den Demos.
2. Er soll möglichst (fast) alle Funktionen/Ressourcen der M32 über I2C "fernsteuerbar" bzw. abfragbar machen.
3. Er soll als I2C-Master eine andere M32, die CCPRO M128 oder die M256 WiFi akzeptieren.
4. Er soll die I2C-Adresse 12 bekommen.
5. Er soll über XBUS INT2 mit dem Master verbunden sein.
6. Er soll wie der Base-Slave auch eine Timeout-Funktion haben.
7. Er soll folgende Befehle (commands) über I2C verstehen:



// Commands:
#define CMD_CONFIGIOS 0
#define CMD_SETIOS 1
//#define CMD_CONFIG 2
#define CMD_SETLEDS 3
#define CMD_DISCHARGEPEAKDETECTOR 4
#define CMD_GETMICROPHONEPEAK 5
#define CMD_SETMEM_CS2 6
#define CMD_WRITESPI 7
#define CMD_WRITEWORDSPI 8
#define CMD_READSPI 9
#define CMD_READWORDSPI 10
#define CMD_SET_WDT 11
#define CMD_SET_WDT_RQ 12
#define CMD_SPI_EEPROM_WRITEBYTE 13
#define CMD_SPI_EEPROM_ENABLEWRITE 14
#define CMD_SPI_EEPROM_DISABLEWRITE 15
#define CMD_SPI_EEPROM_READBYTE 16
#define CMD_SPI_EEPROM_GETSTATUS 17
#define CMD_INITLCD 18
#define CMD_CLEARLCD 19
#define CMD_WRITECHARLCD 20
#define CMD_WRITEINTEGERLCD 21
#define CMD_SETCURSORPOSLCD 22
#define CMD_BEEP 23
#define CMD_SETBEEPERPITCH 24
#define CMD_SOUND 25
Dabei setzt Befehl 0 die 8 freien I/O-Pins der M32 als Ein- oder Ausgänge, Befehl 2 schaltet die einzelnen I/O-Portpins.
Befehl 3 schaltet die LEDs. Befehle 4, 5 gehen mit dem Mikro um.
Befehle 6-10 sind die SPI-Befehle.
Befehle 11,12 gehören zum Watchdog-Timer (wie bei der Base!).
Befehle 13-17 lesen und schreiben von/aus dem SPI-EEPROM auf der M32.
Befehle 18-22 steuern das LCD auf der M32 an.
Befehle 23-25 steuern den Sound mit dem Beeper.

8. Er soll folgende Register zum Lesen durch den Master vorhalten:


#define I2C_REG_STATUS1 0
#define I2C_REG_STATUS2 1
#define I2C_REG_IO_STATUS 2
#define I2C_REG_MEM_CS2 3
#define I2C_REG_SPIBYTE 4
#define I2C_REG_SPIWORD_L 5
#define I2C_REG_SPIWORD_H 6
#define I2C_REG_SPIEEPROMSTATUS 7
#define I2C_REG_SPIEEPROMBYTE 8
#define I2C_REG_SPIEEPROMWORD_L 9
#define I2C_REG_SPIEEPROMWORD_H 10
#define I2C_REG_ADC_4_L 11
#define I2C_REG_ADC_4_H 12
#define I2C_REG_ADC_3_L 13
#define I2C_REG_ADC_3_H 14
#define I2C_REG_ADC_2_L 15
#define I2C_REG_ADC_2_H 16
#define I2C_REG_ADC_6_L 17
#define I2C_REG_ADC_6_H 18
#define I2C_REG_ADC_5_L 19
#define I2C_REG_ADC_5_H 20
#define I2C_REG_ADC_7_L 21
#define I2C_REG_ADC_7_H 22
#define I2C_REG_ADC_MIC_L 23
#define I2C_REG_ADC_MIC_H 24
#define I2C_REG_ADC_KEYPAD_L 25
#define I2C_REG_ADC_KEYPAD_H 26
#define I2C_REG_RELEASEDKEYNUMBER 27
#define I2C_REG_PRESSEDKEYNUMBER 28
#define I2C_REG_LEDS 29
Die REGs 0,1 sind die Interrupt- und Status-Register wie beim Base-Slave.
IO-Status (REG 2) sind die 8 freien I/O-Ports (sofern auf Eingänge geschaltet).
REGs 3-10 sind Leseregister der SPI- und SPI-EEPROM-Funktionen.
REGs 11-23 sind die freien ADC-Kanäle der M32.
REGs 23,24 sind der ADC-Wert des Mikro.
REGs 25,26 sind der ADC-Keypad-Wert.
REGs 27,28 sind die Nummern der zuletzt losgelassenen bzw. gedrückten Taste.
Mit REG 29 läßt sich der aktuelle Stand der 4 LEDs auslesen (an/aus).

9. Er soll auf die RP6Control Library https://www.roboternetz.de/community/showthread.php?47198-RP6Control-M32-Neue-Library-Version-1.3beta aufsetzen. Grund: Die aktuelle Lib V1.32beta ist voll kompatibel zur neuesten Version 1.3 und stellt mit eigenen Tasks schon regelmäßig die ADC-Werte und Werte der I/O-Ports zur Verfügung.

10. Bei Timeout soll die M32 funktionsfähig bleiben (Base-Slave bleibt dann in einer Endlosschleife stehen und muss resettet werden!).

Wenn ihr Ergänzungen möchtet: Hier posten!

Dann mache ich mich demnächst an eine erste Version.
Ist das sonst in der Planung so ok? Vorschläge? Änderungen?


Ich habe auch noch Verständnis-Fragen zum RP6Base-Slave:
... und zwar zu den Stopwatches in der Base-Slave-Demo (RP6Base_I2CSlave.c):

Es werden Stopwatches 1..4 benutzt/gestartet.
- Stopwatch1 wird nur gestartet, aber nicht benutzt: Lasse ich weg. :idea:
- Stopwatch2 ist der Timeout-Zähler, der in signalInterrupt gestartet wird und in clearInterrupt gestoppt/resettet wird. Über 3000 gibt es ein Timeout. Soweit verstehe ich das. In task_update wird Stopwatch2 aber resettet, und zwar im if(getStopwatch4() > 250) - Teil. Das passt eigentlich nicht in die Logik, weil man meinen sollte, dass Stopwatch2 alle 250ms resettet wird. Das macht aber keinen Sinn und findet so auch gar nicht statt, weil Stopwatch4 nie resettet wird. :confused:
- Stopwatch3 steuert die Watchdog-Anfrage. Verstehe ich. :idea:
- Stopwatch4 wird gestartet, nie resettet und resettet anfangs einmalig Stopwatch2 nach 250ms. Warum? Da Stopwatch4 immer weiter durchläuft, wird nach Überlaufen wieder Stopwatch2 einmalig resettet. Das ist mir alles ziemlich unklar. :confused:

Wer kann mir da weiterhelfen und den Sinn erklären?

RolfD
11.09.2012, 17:54
Hallo Dirk,
zu den Soures allgemein, ich hab inzwischen oft festgestellt, das in den RP6 Quellen mal versucht wurde Ideen unter zu bringen die dann aber zum Teil mit ner heißen Nadel zuende gestrickt wurden. D.H. man findet da zuweilen Strukturen und Ansätze (Reste?), die im Prinzip nicht ausgearbeitet sind. manche Stellen sind sogar mit "TODO" markiert. Es gibt aber auch Zusammenhänge, die komplex sind... z.B. alles mit Motoren und Timer.
Slyd hat aber auch immer gesagt das die RP6 Lib ein "Vorschlag" zur Arbeitsgrundlage ist und kein absoluter Weg zur Glücklichkeit - weshalb mich auch wundert das recht wenig an den Libs bisher verbessert wurde im Gegensatz zu anderen Bots mit AVR. Die RP6 Gemeinde ist scheinbar recht genügsam in den Anforderungen... Allerdings hindert wohl die besagte Komplexität auch ein wenig denn es gibt viele Stellschrauben und wenn man nur an einer dreht funktioniert oft nix mehr...

Das ist mir alles ziemlich unklar.
Nicht nur Dir... ich sehs beim überfliegen aber wie du...1 und 4 dürften unnütz sein, 2 und 3 sind "Krücken" um irgendwas abzufangen.. schlimmstenfall weil irgendwo was verbummelt wird. 3 Sek timeout.. tststs is ja schlimmer wie XP *gg

Punkt 10 dürfte problematisch sein auch wenn ich es für erstrebenswert halte.

Bei der SPI-ROM Geschichte... muss man da nicht ganze Pages beschreiben? Macht es Sinn, Daten dann byteweise zu übergeben? Wenn ich vom Master aus 64 Byte ins ROM schreiben will, schreibt man dann da 64*64 Pages? Ich mein... das sind 4096 Page-Schreibvorgänge... das kostet Zeit und der Rom Baustein ist im Nu ausgeleiert... genau so das Micro... macht es Sinn die ADC-Werte des Mikro oder des ADC-Keypad an den Master zu übergeben? Welche Taste gedrückt ist...oder ein Händeklatsch-Event.. oder Frequenterkennung ok.. aber die Auswertung sollte der Slave vorher machen und die Daten fürs I2C Register aufbereiten oder? In der anderen Richtung eben so.. wie beschreibt man dann das LCD4x16? in dem ich da 64 Zeichen plus Steuerzeichen an den Slave morse? Mit zwischendrin Register setzen?
Ein Salve darf ja ruhig dumm sein...aber bissel was sollte der schon vorbereiten den alle paar sec nen adc Wert vom Micro ist für nen Master witzlos. Der Ganze Ansatz mit dem Slaveregister ist eigentlich witzlos... da müsste ein anständiges serielles Protokoll her... sowas z.b. http://de.wikipedia.org/wiki/Modbus ... zu dem Thema hab ich mich aber schon mehrfach ausgelassen.
Punkt 2 dürfte also schwierig werden. Das betrifft übrigends auch alle anderen Slaves die es so für den RP6 gibt. Das möchte ich als "Bedenken" mal anmelden.
Ansonsten denk ich, wenn so "Kinderkrankheiten" ausgemerzt sind, könnte das was werden... da ich mein eigenes Projekt hab, bin ich aber bussy. Ich guck aber gern mal mit bei Dir rein.
LG Rolf

Nachtrag: Die Rechnung mit dem SPI-Rom stimmt so nich.. sind keine 4096 Pages.. nur 4096 Bytes und 64 Page writes... mein Fehler.

Dirk
11.09.2012, 20:43
Hallo Rolf,

... SPI-ROM Geschichte... muss man da nicht ganze Pages beschreiben?
Man muss nicht. Ich denke, dass man da eher auch nur einzelne Bytes schreiben/lesen sollte (vielleicht Einstellungen..?). bzw. der Slave speichert dort Messwerte und der Master fragt sie in kleineren Portionen ab. Im Grunde kann man diese EEPROM-Funktionen auch nur zur Verfügung stellen: Der Programmierer des Masters muss damit adäquat umgehen: Z.B. Page-Grenzen beachten und Adressen verwalten. Die Sinnfrage ist ohnehin immer relativ.

...wie beschreibt man dann das LCD4x16?
Das geht sicher nicht sehr effektiv, aber es geht, zumindest mit Übertragung von Einzelzeichen. Ich könnte auch Strings übertragen, aber das wäre dann doch etwas "übers Ziel hinaus".

macht es Sinn die ADC-Werte des Mikro oder des ADC-Keypad an den Master zu übergeben?
Nicht wirklich, aber Mic und Keypad könnte man theoretisch hardwaremäßig von den ADCs abtrennen für andere Aufgaben. Die Tasten werden ja immerhin ausgewertet (pressed/releasedkeyNumber) ... Aber du hast Recht: Es geht besser.

Kurz noch zu den Stopwatches:
Wenn ich im Base-Slave in der task_update den Anfang so ändere:

if(getStopwatch4() > 250)
{
uBat_measure += adcBat;
uBat_measure /= 2;
uBat_count++;
setStopwatch4(0);
}
... funktioniert tatsächlich auch die Timeout-Funktion des Slaves. Warum ist mir das nicht vorher aufgefallen? Naja, immerhin klappte es ja mit dem Base-Slave.
Jetzt verstehe ich das mit den Stopwatches besser: War wohl ein Bug ...

Filou89
12.09.2012, 08:30
Hallo Zusammen,

Ich könnte auch Strings übertragen, aber das wäre dann doch etwas "übers Ziel hinaus".
Ich würde es für sinnvoll halten, wenn man dem Slave einige "Standard-Strings" beibringen würde die im Programm hinterlegt werden und dann zur ausgabe auf dem LCD nur noch aufgerufen werden müssen.
Im Sinne von:

#define CMD_WRITESTRINGNRLCD 2X
Macht das Sinn?


Punkt 10: Wie stellst du dir das "Weiterleben" vor? Sollen einfach keine neuen Befehle mehr ausgegeben werden, soll eine vordefinierte "Sicherheitsstellung" eingenommen werden, auf dem LCd eine Warnung ausgegeben werden und auf neue I2C Befehle gewartet werden... Als Slave soll er ja nur das tun, was der Master befiehlt.
Mir scheint die "Sicherheitsstellung" sinnvoll. Der Slave würde dann eine Notfallprozedur abarbeiten. Das wäre aber sicher auch anwenderspezifisch; Man könnte jedoch hier eine gute Schnittstelle vorsehen.

Ist für die Ansteuerung der Servos auch etwas vorgesehen?

Grüsse

Filou89
12.09.2012, 10:08
Hi Dirk,
Ich habe mal die Remotrol-Version und Base Version als Vorlage genommen und mal einen Anfang gemacht.
Noch konnte ich nicht alle CMD's schreiben. Manche lesen eigentlich mehr aus als schreiben, andere schreiben und lesen. Das muss noch überarbeitet werden.
Hoffentlich kannst du dies weiterverwenden.
Grüsse
Filou

RolfD
12.09.2012, 14:56
@Filou89
Die Idee mit den Strings per ID aufrufen ist erst mal bestechend gut - schauen wir uns aber mal die Praxis an:
+ Man könnte die Strings im EEPROM oder SPI Rom hinterlegen so das sie nicht im knappen Speicher rumliegen.
- Das ist aber letztlich nur für fixe Strings ohne Variablen sinnvoll.

Möchte ich - was wohl öfter statt findet - z.b. einen String wie "Bat:7,2V LDR_L: 500 LDR_R: 270" ausgeben,
wird schnell klar das es nicht lohnt davon irgendwas vor zu definieren oder man müsste Funktionen basteln die Werte in Platzhalter abgelegter Strings frickeln... erinnert mich irgendwie an printf oder?

Also geht es - für was auch immer - nur um Fixe Strings, ist die Idee gut. Für zusammengesetzte Strings bleibt nur "morsen".

Schön wäre letztlich nur eine Lösung wie es ähnlich mit der RS232 gäbe, in dem man einfach per printf/scanf o.ä. ein Datenstrom auf der I2C verarbeitet und der Slave dies direkt zum Display bringt.
Da sagte aber Dirk leider schon: "übers Ziel hinaus"

Mehrarbeit an einer Stelle führt meist zu weniger Arbeit an vielen anderen Stellen. Leider wird bei den Interfaces gepart, auf vorhandene Lösungen gesetzt und auf Lowlevel programmiert.. nur muss man sich dann nicht über Lowlevelfunktionalität als Ergebnis wundern...

So lässt sich jedenfalls kein vielseitiges, modulares Interface bauen auch wenn es für diese eine Anwendung vielleicht halbwechs funktioniert.

EEPROM bzw. SPI ROM Speicher eignet sich hervorragend um z.B. crc, SIN, COS und ATAN2 Tabellen abzulegen... und vielleicht auch den ein oder anderen String ... aber das ist kein Ersatz für standartisiertes Stringhandling auf seriellen Interfaces jeglicher Bauform. Und genau das Fehlen solcher Konzepte auf dem RP6 erzwingt leider Lowlevel-I2C-Registergefummel-Lösungen.
Natürlich kosten Alternativen auch Speicher aber man spart anderso wo auch - mit etwas Geschick sogar mehrfach. Der Witz ist... solche Lösungen gibts sogar schon - werden aber nicht verwendet.
Stellt euch doch bitte nur mal vor... was man anstellen müsste wenn man 2 RP6 hat.. beide mit RFM12 und M32, wo nun die M32 der RP6_1 Daten auf die Base oder Display vom RP6_2 schreiben/lesen will.... Ok weil die M256 grade "in" ist nehmen wir halt die, statt der RFM12... macht es auch nicht einfacher. Mal abgesehen das 2 RFM12 10 Euro und bissel Hirnschmalz kosten, 2 M256 das 24fache!!!

Ich bin mir aber sicher das Dirk und/oder Du da was funktionierendes zusammen bekommen. Ach wenn es nur eine Lösungs-Replikation der Base_Slave und keine Invention für Serielle Schnittstellen ist - was ja zugegebener Weise auch nicht eure erklärte Aufgabenstellung ist.

Gruß Rolf

Dirk
12.09.2012, 20:07
Ich hab mal hier: http://www.rn-wissen.de/index.php/RP...M32:_I2C-Slave (http://www.rn-wissen.de/index.php/RP6Control_M32:_I2C-Slave)
... einen RN-Wissen Artikel zum M32 I2C-Slave aufgemacht.

Mitschreiben, wer möchte ...

Dirk
13.09.2012, 21:25
Hier: http://www.rn-wissen.de/index.php/RP6Control_M32:_I2C-Slave#I2C-Slave
... gibt es jetzt eine V1.0 des M32 I2C-Slave.

Wenn man die in die M32 lädt, fangen alle 3 Skunden die 4 LEDs an, für 3 Sekunden zu blinken. Das ist die Timeout-Anzeige, die nach 3 Sek. auslöst, dann nach weiteren 3 Sek. Blinken einen "Soft-Reset" auslöst.

Dazu blinkt die Heartbeat-Anzeige (* in der rechten LCD-Ecke).

Würdet ihr das mal testen?
Den M32-Master (am einfachsten RP6Control_07_I2CMaster.c) müßtet ihr für die M256 etwas anpassen.
Die Zeile: if(!block && (PIND & EINT1))
wird in: if(!block && (PINJ & INT2_PI15)) // XBUS INT2 -> PJ6 (PCINT15)
... geändert, weil XBUS INT2 als Interrupt verwendet wird.

Filou89
13.09.2012, 23:21
Also wenn immer die äusseren und die inneren blinken, dann funktioniert das bei mir!
Nur für die als Kosmetik habe ich noch das LCD gelöscht, jedoch nicht über den I2C Bus.
Grüsse

fabqu
14.09.2012, 09:40
Hab mal ne Frage zur Befehlsstruktur unter Punkt 8:
Wollt ihr für #define CMD_SETIOS jeden I/O einzeln setzen?
Oder analog zu SETLEDs auch mehrere auf einmal?
Und wie ists, wenn manche als Input, andere als Output behandelt werden sollten?

Die Idee ist wirklich klasse!
Und der Einschub mit den abgespeicherten Strings finde ich ebenfalls sinnvoll. Man kann ja auf gewisse Ereignisse vordefinierte Strings z.B. ins LCD schreiben lassen etc.

Grüße

Dirk
14.09.2012, 18:42
@Filou89:
Danke für deinen Slave-Code!

Also wenn immer die äusseren und die inneren blinken, dann funktioniert das bei mir!
Ja, so sollte es ohne Master sein. Könntest du das mal mit einem einfachen Master testen (z.B. nur M32-LEDs blinken lassen)?

@fabqu:
Sollten wir die IOs wirklich einzeln als I oder O setzen können? Möglich ist das ...
Mit den Strings muss ich mal überlegen. Im Augenblick möchte ich noch writeStringLCD versuchen ...

Dirk
15.09.2012, 12:21
Im Rn-Wissen Artikel gibt's jetzt die erste Master-Slave Demo:
Ein simples Lauflicht auf der M32, über I2C von der M256 WiFi gesteuert, und mit Timeout-Funktion.

Dazu gehört auch schon eine unfertige Beta-Version der M32 I2C Master Library für die M256 mit den Funktionen zur Steuerung der M32. Diese Library kommt zunächst in den Projektordner,- wenn sie fertig ist später (wie die mitgelieferte RP6M256_I2CMasterLib) auch in den \RP6Lib\RP6control_M256_WIFI Ordner.

Vorschläge?
Insbesondere brauchen wir noch Ideen für die Nachbildung der SPI-Lesefunktionen und der schwierigeren LCD-Funktionen in der Lib...

Schön wäre auch eine Ergänzung der Demo um eine M32 LCD-Ansteuerung und um einen M32 Sound-Test...

Dirk
18.09.2012, 21:27
Hallo Leute,

jetzt gibt es die erste vollständige Version (1.00) der M32 I2C Master Library für die M256 WiFi. :Strahl
Der Slave für die M32 liegt passend in der Version 1.10 vor.

Ich werde jetzt vorläufig nichts weiter ändern, so dass ihr in Ruhe testen könnt.

Wie gefällt's euch?

Max Web
18.09.2012, 23:12
Das sieht sehr gut aus - ich werde das Ganze mal auf mein RNControl (hab kein M32) portieren und eventuell noch eine Unterstützung für ein paar Servos einbauen - dann ist meine Software auf RP6-Seite so gut wie fertig ;)

Dirk
22.09.2012, 20:36
So, jetzt ist auch das "Sahnehäubchen" fertig:

Der "Dual-Slave Master".
Was ist das denn?
Das ist ein I2C-Master-Programm, das gleichzeitig die RP6BASE und die RP6 CONTROL M32 ansteuert.
Ihr findet es hier: http://www.rn-wissen.de/index.php/RP6Control_M32:_I2C-Slave#Dual-Slave_Master

Was kann das Programm:
Es zeigt anfangs Demos für die RP6BASE (MOVE-/ROTATE-Test) und die M32 (LCD-Ausgabe, Sound-Test, SPI-EEPROM Schreib-/Lesetest).
Danach läuft eine Dauerschleife mit je einem Lauflicht auf der RP6BASE und M32 (natürlich vollständig über I2C von der M256 gesteuert!).

Während diese Lauflichter ablaufen, sind insgesamt 8 Event Handler (mit Watchdog Handler: 9!) aktiv:
M32:
--> mem_cs2 Pegel-Wechsel
--> IO-Ports (ins) Pegel-Wechsel
--> Tastenbetätigung
BASE:
--> ACS Zustandswechsel
--> Bumper Zustandswechsel
--> IRCOMM: RC5-Daten empfangen
--> Batteriespannung niedrig
--> Bewegungsstatus

Da kann man ausgiebig testen: Pins der freien IO-Ports der M32 auf andere Pegel legen, Tasten auf der M32 drücken, eine Hand vor den Roboter halten (ACS-Test), Bumper betätigen, RC5-Code senden, (Akku leerlaufen lassen = eher nicht zu empfehlen...).

Der mem_cs2 Pin auf der M32 ist am nicht bestückten IC-Sockel IC5 zu kontaktieren. ACHTUNG: Er ist von der RP6ControlLib auf AUSGANG geschaltet! Also erst auf EINGANG umschalten, bevor man ihn zum Testen des Event Handlers z.B. mit GND oder VCC verbindet.

Testaufbau:
- RP6BASE: RP6Base_I2CSlave.c (aus den Demos des RP6!)
- M32: RP6Control_I2CSlave.c (siehe oben!)
- M256 WiFi: RP6M256_M32_I2CMaster_02.c (siehe oben!)
- M256 WiFi über WLAN und über PROG_UART Stecker mit PC verbunden
- Beide Terminal-Fenster des RobotLoaders ausgeklappt
- Start des Systems über Serial Loader

Damit ist zumindest geklärt, dass man mit der M256 WiFi den Roboter mit M32 komplett über I2C steuern kann.

Jetzt fehlen noch eure Anwendungen ...

Viel Spaß damit!

ex535
29.09.2012, 15:14
Hallo Dirk,

bekomme Fehlermeldung.

Bitte Make File anzeigen.

Compiling: RP6M256_M32_I2CMaster_02.c
avr-gcc -c -mmcu=atmega2560 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=RP6M256_M32_I2CMaster_02.lst -I../../RP6Lib -I../../RP6Lib/RP6control_M256_WIFI -I../../RP6Lib/RP6common -I../../RP6Lib/RP6control_M256_WIFI/sdc -std=gnu99 -MD -MP -MF .dep/RP6M256_M32_I2CMaster_02.o.d RP6M256_M32_I2CMaster_02.c -o RP6M256_M32_I2CMaster_02.o
In file included from RP6M256_M32_I2CMaster_02.c:38:
../../RP6Lib/RP6control_M256_WIFI/RP6M256_M32_I2CMasterLib.h:347: error: expected identifier or '(' before '{' token
make: *** [RP6M256_M32_I2CMaster_02.o] Error 1

> Process Exit Code: 2
> Time Taken: 00:00

Gruß
Kurt

Dirk
29.09.2012, 20:36
Hallo Kurt,

hier das makefile (Ausschnitt):

################################################## #############################
# Target file name (without extension).
# This is the name of your main C source file! Do NOT append the ".c"!
# Example: Let's assume your main source file is "RP6Base_MyProgram.c", then
# you would write: TARGET = RP6Base_MyProgram
TARGET = RP6M256_M32_I2CMaster_02
################################################## #############################

################################################## #############################
# Specify relative path to RP6 library files here.
# This is "../../RP6Lib" or "../RP6Lib" usually.
RP6_LIB_PATH=../../RP6Lib
RP6_LIB_PATH_OTHERS= $(RP6_LIB_PATH)/RP6control_M256_WIFI $(RP6_LIB_PATH)/RP6common
RP6_LIB_PATH_OTHERS += $(RP6_LIB_PATH)/RP6control_M256_WIFI/sdc
################################################## #############################

#------------------------------------------------
# Main Source file is _automatically_ added here:
SRC = $(TARGET).c
# DO NOT EDIT THIS!

################################################## #############################
# If there is more than one source file, append them here separated by spaces.
# Usually you have to add the Library files here! (ONLY add c files "*.c" here,
# NO header files "*.h"!)
# Don't forget to add relative paths!

#SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CslaveTWI.c
SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CmasterTWI.c

SRC += $(RP6_LIB_PATH)/RP6control_M256_WIFI/RP6M256_I2CMasterLib.c
SRC += $(RP6_LIB_PATH)/RP6control_M256_WIFI/RP6M256_M32_I2CMasterLib.c
SRC += $(RP6_LIB_PATH)/RP6control_M256_WIFI/RP6M256Lib.c
SRC += $(RP6_LIB_PATH)/RP6control_M256_WIFI/RP6M256uart.c
SRC += $(RP6_LIB_PATH)/RP6control_M256_WIFI/RP6M256_WIFIlib.c
SRC += $(RP6_LIB_PATH)/RP6control_M256_WIFI/sdc/sd_raw.c
SRC += $(RP6_LIB_PATH)/RP6control_M256_WIFI/sdc/fat.c
SRC += $(RP6_LIB_PATH)/RP6control_M256_WIFI/sdc/partition.c
SRC += $(RP6_LIB_PATH)/RP6control_M256_WIFI/sdc/byteordering.c

-schumi-
30.12.2012, 20:49
Hallo Dirk,

ich möchte gerne dein I2C-Slave-Programm für die M32 Verwenden. Ich habe mir die aktuellen Examples (v1.8, siehe http://www.rn-wissen.de/index.php/RP6_-_Programmierung#Versionen ) heruntergeladen. Dort in "RP6CONTROL_EXAMPLES" einen Ordner "M32-Slave" erstellt. Dort hab ich eine RP6Control_I2CSlave.c mit dem Quelltext von http://www.rn-wissen.de/index.php/RP6Control_M32:_I2C-Slave#Slave erstellt. Dazu das Makefile eines anderen Beispiels kopiert und ein paar Parameter angepasst:


TARGET = RP6Control_I2CSlave

SRC += $(RP6_LIB_PATH)/RP6control/RP6ControlLib.c
SRC += $(RP6_LIB_PATH)/RP6common/RP6uart.c
SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CslaveTWI.c
#SRC += $(RP6_LIB_PATH)/RP6common/RP6I2CmasterTWI.c


Beim übersetzen "make all" bekomme ich aber folgende Fehler:


$ make all

-------- begin --------
avr-gcc (GCC) 4.7.0
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling: RP6Control_I2CSlave.c
avr-gcc -c -mmcu=atmega32 -I. -gdwarf-2 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=RP6Control_I2CSlave.lst -I../../RP6Lib -I../../RP6Lib/RP6control -I../../RP6Lib/RP6common -std=gnu99 -MD -MP -MF .dep/RP6Control_I2CSlave.o.d RP6Control_I2CSlave.c -o RP6Control_I2CSlave.o
RP6Control_I2CSlave.c:96:1: error: unknown type name ‘freeIOs_t’
RP6Control_I2CSlave.c: In function ‘task_update’:
RP6Control_I2CSlave.c:116:5: error: ‘pressedKeyNumber’ undeclared (first use in this function)
RP6Control_I2CSlave.c:116:5: note: each undeclared identifier is reported only once for each function it appears in
RP6Control_I2CSlave.c:129:41: error: ‘ins’ undeclared (first use in this function)
RP6Control_I2CSlave.c:129:60: error: request for member ‘byte’ in something not a structure or union
RP6Control_I2CSlave.c:137:8: error: ‘releasedKeyNumber’ undeclared (first use in this function)
RP6Control_I2CSlave.c: In function ‘task_updateRegisters’:
RP6Control_I2CSlave.c:205:57: error: ‘ins’ undeclared (first use in this function)
RP6Control_I2CSlave.c:214:56: error: ‘adc4’ undeclared (first use in this function)
RP6Control_I2CSlave.c:216:56: error: ‘adc3’ undeclared (first use in this function)
RP6Control_I2CSlave.c:218:56: error: ‘adc2’ undeclared (first use in this function)
RP6Control_I2CSlave.c:220:56: error: ‘adc6’ undeclared (first use in this function)
RP6Control_I2CSlave.c:222:56: error: ‘adc5’ undeclared (first use in this function)
RP6Control_I2CSlave.c:224:56: error: ‘adc7’ undeclared (first use in this function)
RP6Control_I2CSlave.c:226:57: error: ‘adcMic’ undeclared (first use in this function)
RP6Control_I2CSlave.c:228:59: error: ‘adcKeypad’ undeclared (first use in this function)
RP6Control_I2CSlave.c:230:63: error: ‘releasedKeyNumber’ undeclared (first use in this function)
RP6Control_I2CSlave.c:231:62: error: ‘pressedKeyNumber’ undeclared (first use in this function)
RP6Control_I2CSlave.c: In function ‘task_commandProcessor’:
RP6Control_I2CSlave.c:339:4: warning: implicit declaration of function ‘setOUTs’ [-Wimplicit-function-declaration]
RP6Control_I2CSlave.c:343:32: error: ‘adcMic’ undeclared (first use in this function)
RP6Control_I2CSlave.c: In function ‘main’:
RP6Control_I2CSlave.c:472:9: error: request for member ‘byte’ in something not a structure or union
RP6Control_I2CSlave.c:484:3: warning: implicit declaration of function ‘task_RP6M32System’ [-Wimplicit-function-declaration]
make: *** [RP6Control_I2CSlave.o] Fehler 1


Hilfe :)

(Für mich sieht das so aus, als währe eine Lib nicht eingebunden. Aber welche? Und warum meckert er dann nicht?)

Viele Grüße
-schumi-

Dirk
30.12.2012, 21:30
@-schumi-:
Hast du im Abschnitt "Planung" (http://www.rn-wissen.de/index.php/RP6Control_M32:_I2C-Slave#Planung) den Punkt 9 gesehen?

-schumi-
31.12.2012, 00:02
Hi Dirk,

Ja, hab ich. Allerdings hab ich nicht überrissen, dass man die 1.32beta in die 1.3 integrieren soll (Ordner zusammenführen und existierende Dateien überrschreiben) ](*,)

Naja, jetz konnte ich das ganze übersetzen ;)

Herzlichen Dank! :-D

Viele Grüße
-schumi-

Dirk
31.12.2012, 08:16
Super! Dann klappt es ja!

[Vielleicht hätte ich das noch mal im RN-Wissen Artikel im Slave-Abschnitt erwähnen sollen! ...habe ich gerade ergänzt!]

-schumi-
03.01.2013, 22:41
Hallo Dirk,

jetzt hab ich doch noch eine Frage zu deinem M32-Slave-Programm:

Wie kann ich erkennen ob der letzte Befehl (z.B. Buchstabe aufs LCD schreiben) abgeschlossen ist? Weil ich kann inzwischen mit dem Raspberry Pi auf das LCD schreiben, habe aber das Problem, dass wenn ich einen String sende, die Buchstaben so schnell hintereinander gesendet werden, dass das Ganze nicht funktioniert (Es steht dann nur der letzte Buchstabe des Strings auf dem Display).

Ich habe jetzt mal probehalber eine Wartezeit vom 20ms zwischen jedem Buchstaben eingebaut, und schon wird auch der ganze String angezeigt. Aber eine tolle Lösung ist das natürlich nicht...


Leider habe ich deinen Code noch nicht ganz verstanden, und habe überhaupt ein bisschen Probleme mit den Handlern/Watchdogs/Timeouts etc..

Viele Grüße,
-schumi-

Dirk
04.01.2013, 07:48
Hallo -schumi-,

benutzt du für den Raspberry PI auch die Lib "RP6M256_M32_I2CMasterLib" oder schreibst du direkt per I2C auf den Slave?
Wenn du dir in der Lib die Funktion "void writeCharM32LCD(uint8_t ch)" ansiehst, dann wartet die am Ende mit "waitForM32TransmitComplete()" zumindest so lange, bis die I2C-Übertragung des Zeichens abgeschlossen ist. Bei mir war das ausreichend, um jedes Zeichen auf das LCD zu bekommen.

matze1
28.04.2014, 10:28
Servus,

ich versuche gerade die Keys der M32 (als Slave) mit der M256 (als Master) auszulesen.

Mittlerweile funktioniert es, dass ich den pressedkey auslesen kann. Ich würde aber lieber den releasedkey verwenden. Hierbei bekomme ich aber bei allen 5 Tastern immer nur eine '0' zurückgeliefert.

Hoffe, ihr könnt mir helfen.



if(getStopwatch4() > 250)
{
getAllRegisters();


if(interrupt_M32status.keypressed)
{
writeInteger_WIFI(pressedKeyNumber, DEC);
//writeInteger_WIFI(releasedKeyNumber, DEC);
writeChar_WIFI('\n');

}

//if(interrupt_M32status.keychange)
// {
//// writeInteger_WIFI(pressedKeyNumber, DEC);
//writeInteger_WIFI(releasedKeyNumber, DEC);
// writeChar_WIFI('\n');

// }

setStopwatch4(0);
}

Dirk
28.04.2014, 16:29
Hi matze1,
solange eine Taste gedrückt wird, enthält pressedKeyNumber die Nummer der Taste und releasedKeyNumber 0.
Solange keine Taste gedrückt wird, enthält pressedKeyNumber 0 und releasedKeyNumber die Nummer der zuletzt gedrückten Taste.

Eine Abfrageschleife kann z.B. so aussehen:

uint8_t last_releasedKeyNumber;

/**
* M32 key state changed
*/
void keyStateChanged(void)
{
writeString_P_WIFI("\n\n===> key state changed!!!\n");
writeString_P_WIFI("ADC_KEYPAD value: ");
writeInteger_WIFI(adcKeypad, DEC);
writeChar_WIFI('\n');
writeString_P_WIFI("Key is pressed: ");
if(interrupt_M32status.keypressed) writeString_P_WIFI("Yes\n");
else writeString_P_WIFI("No\n");
writeString_P_WIFI("[Last rel. key number: ");
writeInteger_WIFI(last_releasedKeyNumber, DEC);
writeString_P_WIFI("]\nReleased key number: ");
writeInteger_WIFI(releasedKeyNumber, DEC);
writeChar_WIFI('\n');
last_releasedKeyNumber = releasedKeyNumber;
writeString_P_WIFI("Pressed key number: ");
writeInteger_WIFI(pressedKeyNumber, DEC);
writeChar_WIFI('\n');
writeChar_WIFI('\n');
}

uint8_t regM32Buf[4];

while(true)
{
task_checkPCINT15(); // RP6 M32 main task
if(interrupt_M32status.keyChange)
{
I2CTWI_readRegisters(I2C_RP6_M32_ADR, I2C_REG_ADC_KEYPAD_L, regM32Buf, 4);
adcKeypad = regM32Buf[0] + (regM32Buf[1]<<8);
releasedKeyNumber = regM32Buf[2];
pressedKeyNumber = regM32Buf[3];
keyStateChanged();
}
task_I2CTWI();
}