PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RP6_M32 - M32 soll das was per uart geschick wird im Display ausgeben !?!



AsuroPhilip
21.05.2011, 21:44
Hallo,

stehe mal wieder auf`m Schlauch ;->

Ist es möglich, wenn ich im RP6_Loader, "123" tippe und es absende, dass es im Display steht???

Habe schon viel probiert und gegooglet, habs aber nicht geschaft :( .

Hoffe ihr könnt mir helfen ;->


Vielen Dank
Philip :cool:

RolfD
22.05.2011, 08:02
Na das läuft auf ein recht einfaches getchar/putchar hinaus.... Schau mal da....
https://www.roboternetz.de/community/showthread.php?53205-Problem-mit-UART-Progr%E4mchen
Gefunde mit Forensuche "Terminal"

AsuroPhilip
22.05.2011, 10:46
Vielen Dank ;->

Hat geklappt *happy*

Könnte ich den auch damit eine Servo steuern?

Code:


#include "RP6ControlLib.h"
#include "RP6ControlServoLib.h"
#include "RP6uart.h"


char Buffer[UART_RECEIVE_BUFFER_SIZE + 1];


uint8_t Eingabe(void){

static buffer_pos = 0;
if(getBufferLength()){
Buffer[buffer_pos]=readChar();
if(Buffer[buffer_pos]=='\n'){
Buffer[buffer_pos] = '\0';
buffer_pos = 0;
return 1;
}
else if(buffer_pos >= UART_RECEIVE_BUFFER_SIZE) {
Buffer[UART_RECEIVE_BUFFER_SIZE] = '\0';
buffer_pos = 0;
return 2;
}
buffer_pos++;
}
return 0;
}

void Warten(void){

while(!Eingabe());

}



int main(void)
{

initRP6Control();
initLCD();


setLEDs(0b111111);
mSleep(500);
setLEDs(0b000000);

initSERVO(SERVO1);


while(true)
{
Warten();
setCursorPosLCD(0, 0);
writeStringLCD(Buffer);

servo1_position = Buffer;




task_SERVO();


mSleep(3);
}
return 0;
}

Egal was ich abschicke, der Servo zappelt immer nur kurz hoch.


mfG
Philip

Richard
22.05.2011, 11:56
Vielen Dank ;->

Hat geklappt *happy*

Könnte ich den auch damit eine Servo steuern?

Code:


#include "RP6ControlLib.h"
#include "RP6ControlServoLib.h"
#include "RP6uart.h"


char Buffer[UART_RECEIVE_BUFFER_SIZE + 1];


uint8_t Eingabe(void){

static buffer_pos = 0;
if(getBufferLength()){
Buffer[buffer_pos]=readChar();
if(Buffer[buffer_pos]=='\n'){
Buffer[buffer_pos] = '\0';
buffer_pos = 0;
return 1;
}
else if(buffer_pos >= UART_RECEIVE_BUFFER_SIZE) {
Buffer[UART_RECEIVE_BUFFER_SIZE] = '\0';
buffer_pos = 0;
return 2;
}
buffer_pos++;
}
return 0;
}

void Warten(void){

while(!Eingabe());

}



int main(void)
{

initRP6Control();
initLCD();


setLEDs(0b111111);
mSleep(500);
setLEDs(0b000000);

initSERVO(SERVO1);


while(true)
{
Warten();
setCursorPosLCD(0, 0);
writeStringLCD(Buffer);

servo1_position = Buffer;




task_SERVO();


mSleep(3);
}
return 0;
}

Egal was ich abschicke, der Servo zappelt immer nur kurz hoch.


mfG
Philip

Mit C kenne ich mich kaum aus, aber aber Du liest ein Char(), die PWM für ein Servo braucht aber einen Zahlen Wert?
z.B. 0...255 oder täusche ich mich jetzt?

Gruß Richard

SlyD
22.05.2011, 13:11
Ne char ist egal aber

servo1_position = Buffer;

das ist böse. Du weist den ZEIGER Buffer als wert für servo1_position zu.

Du musst auch noch die ASCII Zeichen vom PC umwandeln.
Schau Dir mal das Selftest Programm an.
Oh und natürlich die Beispielprogramme zum UART (RP6BASE examples) da ist das auch gezeigt!

MfG,
SlyD

AsuroPhilip
22.05.2011, 14:08
servo1_position = Buffer;

das ist böse. Du weist den ZEIGER Buffer als wert für servo1_position zu.

Du musst auch noch die ASCII Zeichen vom PC umwandeln.


Wie wandelt man das denn um?

Weil wenn ich 12 schreibe, steht im LCD auch 12, und diese 12 soll dann die servo1_position sein. Und wenn dan ne 13 kommt soll dann natürlich die servo1_position 13 sein.


mfG
Philip

SlyD
22.05.2011, 14:19
> wenn ich 12 schreibe, steht im LCD auch 12,

Klar, Das LCD versteht ja auch ASCII Codes also muss da nix umgewandelt werden :)


s. z.B. RP6Base_Selftest.c ab Zeile 1265



if(getInputLine())
{
...
...
{
pwm_tmp = atoi(receiveBuffer);

... fehlercheck ...

if(pwm_tmp > 120){pwm_tmp = 120; writeString_P("\n--> Power limited to 120!");}
else if(pwm_tmp < 0) {pwm_tmp = 0;}
pwm = pwm_tmp;

writeString_P("\n--> Change speed to:");
writeInteger(pwm_tmp,DEC);
writeChar('\n');

setMotorPower(pwm,pwm);
}




MfG,
SlyD

AsuroPhilip
22.05.2011, 20:05
Danke, hat geklappt ;->

Kann ich auch mehrere Servos so steuern?

Also wenn ich sende "1:100" soll der erste Servo auf 100 und wenn ich "2:50" sende der 2. auf 50, oder geht das nicht, bzw. anders?

mfG
Philip

AsuroPhilip
23.05.2011, 14:28
Also wenn ich sende "1:100" soll der erste Servo auf 100 und wenn ich "2:50" sende der 2. auf 50, oder geht das nicht, bzw. anders?

Keiner ne Idee?

RolfD
23.05.2011, 14:55
Keiner ne Idee?

Der Thread heist "RP6_M32 - M32 soll das was per uart geschick wird im Display ausgeben !?!"
und nicht "Also wenn ich sende "1:100" soll der erste Servo auf 100 und wenn ich "2:50" sende der 2. auf 50,"

Meine Idee wäre.. du versuchst es mal selbst mit nachdenken...

Und nein ich bin nicht unfreundlich - aber das Du nach nicht mal 24 h schon off topic und ungeduldig nachstocherst ... ist unfein - und mit Verlaub - macht mich stinke stock sauer.

AsuroPhilip
23.05.2011, 15:03
Der Thread heist "RP6_M32 - M32 soll das was per uart geschick wird im Display ausgeben !?!"
und nicht "Also wenn ich sende "1:100" soll der erste Servo auf 100 und wenn ich "2:50" sende der 2. auf 50,"

Soll ich den für eine frage nen neuen Thread aufmachen?

RolfD
23.05.2011, 15:04
Les mal noch nen kleines Stück weiter.. da steht meine Empfehlung...

AsuroPhilip
29.05.2011, 16:18
Okay habe das so erstmal geschaft, aber es gibt schon wieder ein neues problem.
Wenn ich es so mache:


void task_befehle(void)
{
Eingabe();

long pos = atoi(Buffer);


if(pos < 180 && pos > 0)
{
servo1_position = pos;
}
else
if(pos < 360 && pos > 180)
{
servo2_position = pos - 180;
}
else
if(pos < 540 && pos > 360)
{
servo3_position = pos - 360;
}
else
if(pos == -1)
{
I2CTWI_transmitByte(PCF, 0);
}
else
if(pos == -2)
{
I2CTWI_transmitByte(PCF, 3);
}

}

void task_sensoren(void)
{
getAllSensors();
writeIntegerLength((((adcBat/102.4f)+0.1f)), DEC, 2);
writeString_P(".\n");
writeIntegerLength((((adcBat/1.024f)+10)), DEC, 2);
writeString_P("V\n");
writeIntegerLength(adcLSL,DEC,4);
writeString_P("L\n");
writeIntegerLength(adcLSR,DEC,4);
writeString_P("R\n");
}

uint32_t Eingabe(void){

static buffer_pos = 0;

if(getBufferLength())
{
Buffer[buffer_pos]=readChar();

if(Buffer[buffer_pos]=='\n')
{
Buffer[buffer_pos] = '\0';
buffer_pos = 0;

return 1;
}

else if(buffer_pos >= UART_RECEIVE_BUFFER_SIZE)
{
Buffer[UART_RECEIVE_BUFFER_SIZE] = '\0';
buffer_pos = 0;

return 2;
}

buffer_pos++;
}
return 0;
}

int main(void)
{

initRP6Control();
initLCD();
initSERVO(SERVO1 | SERVO2 | SERVO3);

WDT_setRequestHandler(watchDogRequest);

I2CTWI_initMaster(100);
I2CTWI_setRequestedDataReadyHandler(I2C_requestedD ataReady);
I2CTWI_setTransmissionErrorHandler(I2C_transmissio nError);


setLEDs(0b111111);
mSleep(500);
setLEDs(0b000000);

I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT, true);
I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, CMD_SET_WDT_RQ, true);
I2CTWI_transmitByte(PCF, 0);



while(true)
{
task_I2CTWI();
task_befehle();
task_sensoren();
task_SERVO();
}
return 0;
}
Zappeln die Servos nur rum und die Sensordaten ändern sich nicht.

Empfangen mache ich in Visual C# so :



public void Daten_Empfangen()
{
string[] Volt = serialPort1.ReadLine().Split('.');
string[] LVolt = serialPort1.ReadLine().Split('V');
string[] Licht = serialPort1.ReadLine().Split('L');
string[] LLicht = serialPort1.ReadLine().Split('R');
string Akku = Volt[0] + LVolt[0];
string Licht_L = Licht[0];
string Licht_R = LLicht[0];

label9.Text = Volt[0].Replace("0", "") + "." + LVolt[0] + " Volt";

if (Convert.ToInt32(Akku) > progressBar1.Maximum)
{
progressBar1.Maximum = Convert.ToInt32(Akku);
}
else
progressBar1.Value = Convert.ToInt32(Akku);

if (Convert.ToInt32(Licht_R) > progressBar2.Maximum)
{
progressBar2.Maximum = Convert.ToInt32(Licht_R);
}
else
progressBar2.Value = Convert.ToInt32(Licht_R);


if (Convert.ToInt32(Licht_L) > progressBar3.Maximum)
{
progressBar3.Maximum = Convert.ToInt32(Licht_L);
}
else
progressBar3.Value = Convert.ToInt32(Licht_L);

}

private void timer2_Tick(object sender, EventArgs e)
{
if (checkBox1.Checked)
{
Daten_Empfangen();
}
}Hoffe ihr könnt mir nochmal helfen.

mfG
Philip

Fabian E.
29.05.2011, 17:29
Und was genau sendest du vom PC aus?

AsuroPhilip
29.05.2011, 17:33
Und was genau sendest du vom PC aus?

Senden tuhe ich das :


private void trackBar2_Scroll(object sender, EventArgs e)
{
int servo2label = trackBar2.Value - 180;
label5.Text = servo2label.ToString();

serialPort1.Write(trackBar2.Value.ToString());
serialPort1.Write("\n\r");
}

private void trackBar1_Scroll(object sender, EventArgs e)
{
label1.Text = trackBar1.Value.ToString();

serialPort1.Write(trackBar1.Value.ToString());
serialPort1.Write("\n\r");
}

private void trackBar3_Scroll(object sender, EventArgs e)
{
int servo3label = trackBar3.Value - 360;
label3.Text = servo3label.ToString();
serialPort1.Write(trackBar3.Value.ToString());
serialPort1.Write("\n\r");

}

Fabian E.
29.05.2011, 17:40
Naja, bei jedem empfangenen Zeichen wird deine Buffer Position wieder auf Null gesetzt...
Das kann ja schonmal nicht klappen. Außerdem wertest du auch den Rückgabewert der "Eingabe"-Funktion nicht aus. Das dürfte auch dazu führen, dass das Ganze nicht klappt.

Das Senden der Werte sieht mir auch etwas seltsam aus, es sieht so aus als ob du denkst, dass die modifizierten TrackBar-Werte gesendet werden ("-360","-180").
Das werden sie aber sicherlich nicht.

AsuroPhilip
29.05.2011, 17:44
Das Senden der Werte sieht mir auch etwas seltsam aus, es sieht so aus als ob du denkst, dass die modifizierten TrackBar-Werte gesendet werden ("-360","-180").
Das werden sie aber sicherlich nicht.

Nein das ist nur für ein Label, senden tuhe ich ich bei trackbar1 0 - 180 bei trackbar2 180 - 360 und bei trackbar3 360 - 540.

Fabian E.
29.05.2011, 17:48
Nein das ist nur für ein Label, senden tuhe ich ich bei trackbar1 0 - 180 bei trackbar2 180 - 360 und bei trackbar3 360 - 540.
ach dann soll das deine deine Lösung für "1:100" sein, okay. Das ist dann natürlich okay so.

Allerdings ändert sich an den anderen Punkten nichts, die sind immernoch falsch.

AsuroPhilip
29.05.2011, 17:53
ach dann soll das deine deine Lösung für "1:100" sein, okay. Das ist dann natürlich okay so.
Ja mir ist nichts anderes eingefallen ;->



Außerdem wertest du auch den Rückgabewert der "Eingabe"-Funktion nicht aus

Wie werte ich die denn richtig aus?

Fabian E.
29.05.2011, 17:55
Ja mir ist nichts anderes eingefallen ;->
Wie werte ich die denn richtig aus?

Hm? Du gibst doch einen Wert zurück aus der Funktion, dann musst du doch auch irgendwas damit machen...
In deinem Fall eben prüfen, ob die gesamte Zahl übertragen wurde...

AsuroPhilip
29.05.2011, 18:04
Hm? Du gibst doch einen Wert zurück aus der Funktion, dann musst du doch auch irgendwas damit machen...
In deinem Fall eben prüfen, ob die gesamte Zahl übertragen wurde...

Ich mache doch was damit:


if(pos < 180 && pos > 0)
{
servo1_position = pos;
}
else
if(pos < 360 && pos > 180)
{
servo2_position = pos - 180;
} .....

oder verstehe ich da was falsch?

Fabian E.
29.05.2011, 18:29
oder verstehe ich da was falsch?
Jep, da verstehst du was falsch.
Die Funktion "Eingabe()" liefert dir ja einen Wert zurück. Dieser Wert gibt an, ob die aktuelle Übertragung des Servowerts schon abgeschlossen ist.
Daher musst du natürlich erst auf das Ende warten, bevor du deine Servos einstellen kannst.

Weißt du denn überhaupt, was der Rückgabewert einer Methode ist?

AsuroPhilip
29.05.2011, 19:03
Weißt du denn überhaupt, was der Rückgabewert einer Methode ist?

Nein, aber ich denke da fehlt noch "while(!Eingabe());"?

Aber dann werden die Sensorwerte nicht geschickt. (bzw. nur wenn ich die servos umstelle)

Fabian E.
29.05.2011, 19:06
Hm, dann solltest du dich definitiv erst mal mit den Grundlagen von "C" vertraut machen.
Prinzipiell hast du mit deinem Vorschlag aber fast Recht. Du musst solange warten, bis die Methode den paasenden Wert zurückliefert.
Dazu sind nur kleine Anpassungen an dem eben geposteten Code nötig.

AsuroPhilip
29.05.2011, 19:14
Hm, dann solltest du dich definitiv erst mal mit den Grundlagen von "C" vertraut machen.
Prinzipiell hast du mit deinem Vorschlag aber fast Recht. Du musst solange warten, bis die Methode den paasenden Wert zurückliefert.
Dazu sind nur kleine Anpassungen an dem eben geposteten Code nötig.

Aber dann werden die Sensorwerte nicht geschickt. (bzw. nur wenn ich die servos umstelle)
Kann man das auch machen das dann die sensorwerte immer noch geschickt werden?

AsuroPhilip
01.06.2011, 15:00
@Fabian E. Dein Postfach ist voll ;->

Kennt jemand eine methode um uart zu empfangen, aber so, dass das Programm nicht die while schleife blockiert??

mfG
Philip

Fabian E.
01.06.2011, 15:07
Immer noch ?? Das hatte ich eigentlich komplett gelöscht als die Benachrichtigung kam...

AsuroPhilip
01.06.2011, 15:20
@Fabian E.
Wie empfängst du die Daten, in deinem C# programm??

Fabian E.
01.06.2011, 15:21
Die Klasse heißt SerialPort.

AsuroPhilip
01.06.2011, 15:23
Ja soweit bin ich auch gekommen ;->

Ich meine du sendest ja "Bat: 123" wie "schneidest" du das "Bat: " aus?

radbruch
01.06.2011, 15:27
Der USART kann einen Interrupt auslösen, wenn er ein Zeichen empfangen hat:
http://www.rn-wissen.de/index.php/UART_mit_avr-gcc#Variante_2:_Mit_Interrupts
http://www.tschallener.net/AVR/intr_usart.pdf

Der RP6 verwendet das offensichtlich schon in seiner Lib:

/**
* UART receive ISR.
* Handles reception to circular buffer.
*/
ISR(USART_RXC_vect)
{
static volatile uint8_t dummy;
if(((uint8_t)(write_size - read_size)) < UART_RECEIVE_BUFFER_SIZE) {
uart_receive_buffer[write_pos++] = UDR;
write_size++;
if(write_pos > UART_RECEIVE_BUFFER_SIZE)
write_pos = 0;
}
else {
dummy = UDR;
uart_status = UART_BUFFER_OVERFLOW;
}
}
(Aus RP6uart.c)

In RP6RobotBaseLib.c wird in initRobotBase() der entsprechende Receive-Interrupt freigegeben:

UCSRB = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE);

Fabian E.
01.06.2011, 15:29
Naja, das ist simple Stringverarbeitung... Das hat erstmal nichts mit dem RP6 zu tun sondern ist einfach Grundlagenwissen in C#.
Guck dir mal die Methoden an, die ein String bereitstellt...

AsuroPhilip
01.06.2011, 16:18
@radbruch

Senden tuht er jetzt ununterbrochen (soll ja auch so sein!)
Aber er "hört" nicht auf mich... und die Servos gehen in die MAX stellung?!?


void task_befehle(void)
{
char uart_receive_buffer[UART_RECEIVE_BUFFER_SIZE+1];

uint8_t uart_status;
uint8_t read_pos = 0;
uint8_t write_pos = 0;
uint8_t read_size = 0;
uint8_t write_size = 0;

static uint8_t dummy;
if(((uint8_t)(write_size - read_size)) < UART_RECEIVE_BUFFER_SIZE)
{
uart_receive_buffer[write_pos++] = UDR;
write_size++;
if(write_pos > UART_RECEIVE_BUFFER_SIZE)
write_pos = 0;
uart_status = UART_BUFFER_OK;
}
else
{
dummy = UDR;
uart_status = UART_BUFFER_OVERFLOW;
}


long pos = atoi(uart_receive_buffer);


if(pos < 180 && pos > 0)
{
servo1_position = pos;
}
else
if(pos < 360 && pos > 180)
{
servo2_position = pos - 180;
}
else
if(pos < 540 && pos > 360)
{
servo3_position = pos - 360;
}
else
if(pos == -1)
{
I2CTWI_transmitByte(PCF, 0);
}
else
if(pos == -2)
{
I2CTWI_transmitByte(PCF, 3);
}
}

Fabian E.
01.06.2011, 19:24
Okay, was soll das denn mal werden? Das sieht mir irgendwie schwer kompliziert aus...
Aber du hast meinen Tipp imernoch nicht berücksichtigt. Du liest immer nur das erste Zeichen aus.
Dann stellst du sofort deinen Servo auf dieses erste Zeichen. Du musst erst warten, bis die komplette Zahl übertragen wurde.

AsuroPhilip
01.06.2011, 19:30
Das sieht mir irgendwie schwer kompliziert aus...
Ja, finde ich auch!


Du liest immer nur das erste Zeichen aus.
Dann stellst du sofort deinen Servo auf dieses erste Zeichen. Du musst erst warten, bis die komplette Zahl übertragen wurde.

Das ist das Problem, wenn ich "while(!Eingabe());" schreibe blockiert das solange die while-schleife bis ich was vom Pc schicke!

Fabian E.
01.06.2011, 19:32
Nur mal so als Anregung... Aus meinem eigenen Code...


if(getBufferLength())
{
char tmp = readChar();
if (tmp =='#')
{
mSleep(10);
counter = 0;
}
text[counter] = tmp;
text[counter + 1] = '\0';
counter++;
}
int cmd = getCommand();
if(cmd)
{
[..]
}

AsuroPhilip
01.06.2011, 20:00
Also muss man nur
if(cmd) { [..] } dahintermachen?

So klappt es nicht:




void lesen(void)
{
char text[50];
int counter = 0;

if(getBufferLength())
{
char tmp = readChar();
if (tmp =='\n')
{
mSleep(10);
counter = 0;
}
text[counter] = tmp;
text[counter + 1] = '\0';
counter++;
}
long cmd = atoi(text);
if(cmd)
{
if(cmd == -1)
{
I2CTWI_transmitByte(PCF, 0);
}
else
if(cmd == -2)
{
I2CTWI_transmitByte(PCF, 3);
}
}
}

SlyD
02.06.2011, 09:58
Ganz allgemeiner Tipp (ohne den Code nachvollzogen zu haben):
Sinnvolle TEXTAUSGABEN zum debuggen in den Code reinmachen damit Du sehen kannst was wo wie passiert.
Auch die Werte ausgeben lassen mit writeInteger und writeString ...

MfG,
SlyD

Fabian E.
02.06.2011, 13:52
Nein, du hast einen ganz wichtigen (eigentlich den WICHTIGSTEN) Teil des Codes gerade gelöscht :P
Du must nun eine Funktion getCommand() schreiben, die den übertragenen String in einen Befehl umwandelt ;)

AsuroPhilip
05.06.2011, 12:19
Du must nun eine Funktion getCommand() schreiben, die den übertragenen String in einen Befehl umwandelt ;)

Ich brauche doch nur die Zahl, die ich per Uart schicke!

Habs so versucht, klappt nicht:



char Buffer[UART_RECEIVE_BUFFER_SIZE + 1];

uint32_t Eingabe(void){

static buffer_pos = 0;

if(getBufferLength())
{
Buffer[buffer_pos]=readChar();

if(Buffer[buffer_pos]=='\n')
{
buffer_pos = 0;

return 1;
}

else if(buffer_pos >= UART_RECEIVE_BUFFER_SIZE)
{
buffer_pos = 0;

return 2;
}

buffer_pos++;
}
return 0;
}

void task_befehle(void)
{
Eingabe();
if(Eingabe())
{
long pos = atoi(Buffer);


if(pos < 180 && pos > 0)
{
servo1_position = pos;
}
else
if(pos < 360 && pos > 180)
{
servo2_position = pos - 180;
}
else
if(pos < 540 && pos > 360)
{
servo3_position = pos - 360;
}
else
if(pos == -1)
{
I2CTWI_transmitByte(PCF, 0);
}
else
if(pos == -2)
{
I2CTWI_transmitByte(PCF, 3);
}
}

}Edit:
hab mir mal den wert von pos anzeigen lassen, ist wenn ich eine zahl sende, sendet er mir das zurück! Wenn ich mehrer Zahlen sende macht er nicht!

Edit2: Vielleicht mache ich es doch wie Fabian! @Fabian E. was sendes du denn von pc aus?

Fabian E.
05.06.2011, 12:38
Sag ich ja, du benutzt immer nur die erste Zahl.
Du musst dir irgendein "Endzeichen" definieren, an dem du erkennst, dass alle Ziffern gesendet wurden...
Wenn dieses Endzeichen auftritt kannst du die Servoposition setzen.

AsuroPhilip
05.06.2011, 12:41
das endzeichen ist doch "\n" oder muss mir da was anderes ausdenken (*, #, .)?

Fabian E.
05.06.2011, 13:20
Naja, wenn das automatisch mitgesendet wird... Das weiß ich nicht, kommt drauf an ob dein Termonal Programm das macht.
Du überprüfst zwar ob das Zeichen \n ist, du reagierst aber nicht darauf.
NUR DANN wenn auch wirklich ein \n empfangen wird darfst du weiter machen.

AsuroPhilip
05.06.2011, 14:31
Ja, hab es mit * gemacht und es klappt ;->