Jump to content

C/C++-Programm auf RED-Brick reagiert nicht auf Rotary Encoder 2.0


Recommended Posts

Hallo.

Ich habe in C/C++ ein "Programm" geschrieben, welches die Counts eines Rotary Encoders als Eingabe für verschiedene Parameter benutzt. Die Parameter werden auf einem LCD128x64 über Buttons ausgewählt (s. Anhang IMG_6043.jpg).

Hardware: Redbrick mit Silent Stepper Brick. An letzterem hängt ein LCD128x64 und ein Rotary Encoder V2.

Das Programm macht das was es soll, solange ich es auf meinem PC starte, der über USB mit dem RED Brick verbunden ist (soweit ich das verstehe, läuft dann das Programm über den Brick Daemon).

Compiliere ich das Programm auf dem RED-Brick, und stelle "Autostart" ein, dann läuft das Programm ohne Fehlermeldung, die Bedienung des LCD128x64 funktioniert auch, nur das Drehen am Encoder wird nicht erkannt.

Starte ich den Brick-Viewer auf dem RED-Brick, dann reagiert der wie erwartet, wenn man am Rotary Encoder dreht.

Nachdem ich die FAQs durchgelesen habe, habe ich den Verdacht dass es an der Callback-Funktion liegt - aber ich kann mir keinen Reim drauf machen

Das "Programm" ist momentan im Prototypen-Status. Die globalen Definitionen und main() sieht folgendermassen aus.

#include <iostream>
#include <sstream>

#define IPCON_EXPOSE_MILLISLEEP
#include "ip_connection.h"
#include "bricklet_lcd_128x64.h"
#include "brick_silent_stepper.h"
#include "bricklet_rotary_encoder_v2.h"

#define HOST "localhost"
#define PORT 4223
#define UID_LCD128x64 "R2d"
#define UID_SILENTSTEPPER01 "6Sy4c8"
#define UID_rotEnc01 "KcD"

#define STEPPER01_ACCELERATION 5000
#define STEPPER01_DEACCELERATION 5000
#define STEPPER01_CURRENT 800
#define STEPPER01_MAX_Umin 120

#define LCD128x64_TABHOME 0
#define LCD128x64_TABREG1 1
#define LCD128x64_TABREG2 2
#define LCD128x64_TABNH3 3

#define LCD128x64_ButtonStart 1
#define LCD128x64_ButtonStop 2
#define LCD128x64_ButtonAus 3
#define LCD128x64_ButtonFlow 4
#define LCD128x64_ButtonCalFactor 5
#define LCD128x64_ButtonDosingInterval 6
#define LCD128x64_ButtonDelayInterval 7

IPConnection ipcon;
LCD128x64 lcd01;
bool lcd01_created;
SilentStepper SilentStepper01;
RotaryEncoderV2 RotEnc01;
int32_t countRotEnc01;
uint8_t ID_LCD128x64_MenuePunkt;
uint8_t ID_LCD128x64_Tab;

char text01[22];
char text02[22];
char text03[22];
char text04[22];

struct PeristalticPump
{
    uint8_t PumpID;
    char PumpName[4];
    char LiquidName[6];
    char FlowMLPerHour_Name[11];
    uint16_t FlowMLPerHour_Value;
    char DosingIntervalTimeMinute_Name[11];
    uint8_t DosingIntervalTimeMinute_Value;
    char DelayIntervalTimeMinute_Name[11];
    uint8_t DelayIntervalTimeMinute_Value;
    char CalibrationFactorPercent_Name[11];
    uint8_t CalibrationFactorPercent_Value;
    uint16_t RoundsPer100mL;
//    float TubeInnerDiameterMM;
//    bool FlowDirectionClockwise;
    SilentStepper *SilentStepper01;
    LCD128x64 *lcd01;
    uint8_t TabIndex;
    uint8_t ButtonIndex;
};

PeristalticPump pump;

void cb_count02(int32_t count, PeristalticPump &ActivePump);
void cb_ispressed01(PeristalticPump &ActivePump);
void cb_gui_button_pressed01(uint8_t index, bool pressed, PeristalticPump &ActivePump);
void cb_gui_tab_selected(int8_t index, PeristalticPump &ActivePump);
void LCD128x64_HomeScreen(PeristalticPump &ActivePump);
void LCD128x64_REG1(PeristalticPump &ActivePump);
void Motor(PeristalticPump &ActivePump);
void MotorContinuousModeStart(PeristalticPump &ActivePump);
void MotorStop(PeristalticPump &ActivePump);

int main(void)
{
	ipcon_create(&ipcon);
    lcd_128x64_create(&lcd01, UID_LCD128x64, &ipcon);
	silent_stepper_create(&SilentStepper01, UID_SILENTSTEPPER01, &ipcon);
	rotary_encoder_v2_create(&RotEnc01, UID_rotEnc01, &ipcon);

	if(ipcon_connect(&ipcon, HOST, PORT) < 0)
    {
		fprintf(stderr, "Could not connect\n");
		return 1;
    }
  	lcd_128x64_register_callback(&lcd01,
	                             LCD_128X64_CALLBACK_GUI_TAB_SELECTED,
	                             (void (*)(void))cb_gui_tab_selected,
	                             &pump);
    lcd_128x64_register_callback(&lcd01,
                                 LCD_128X64_CALLBACK_GUI_BUTTON_PRESSED,
                                 (void (*)(void))cb_gui_button_pressed01,
                                 &pump);

    rotary_encoder_v2_register_callback(&RotEnc01, ROTARY_ENCODER_V2_CALLBACK_COUNT,
                                        (void (*)(void))cb_count02, &pump);

    rotary_encoder_v2_set_count_callback_configuration(&RotEnc01, 500, false, 'x', 0, 0);
    lcd_128x64_set_gui_button_pressed_callback_configuration(&lcd01, 1000, true);
	lcd_128x64_set_gui_tab_selected_callback_configuration(&lcd01, 1000, true);

    pump.lcd01 = &lcd01;
    LCD128x64_HomeScreen(pump);


    printf("Press key to exit\n");
    getchar();
	silent_stepper_stop(&SilentStepper01); // Request motor stop
    silent_stepper_set_speed_ramping(&SilentStepper01, STEPPER01_ACCELERATION, STEPPER01_DEACCELERATION);
	millisleep(400); // Wait for motor to actually stop: max velocity (2000 steps/s) / decceleration (5000 steps/s^2) = 0.4 s
	silent_stepper_disable(&SilentStepper01); // Disable motor power

	silent_stepper_destroy(&SilentStepper01);
	lcd_128x64_destroy(&lcd01);
	rotary_encoder_v2_destroy(&RotEnc01);


	ipcon_destroy(&ipcon); // Calls ipcon_disconnect internally
	return 0;
}

Hat jemand eine Idee, warum alles funktioniert bis auf den Encoder?

Gruss

Uwe

 

 

IMG_6043.JPG

Link zu diesem Kommentar
Share on other sites

Danke für die Rückmeldung.

Wenn ich das Programm vom PC aus starte dann liefert

    printf("return value: %d \n",rotary_encoder_v2_set_count_callback_configuration(&RotEnc01, 500, false, 'x', 0, 0));

auf der Console: "return value: 0"

Im Brick Viewer Log hat es folgende Einträge drin:

Zitat

2020-11-09 00:37:10.729731 <I> <main_linux.c:334> Brick Daemon 2.4.0+redbrick started (pid: 619, daemonized: 1)

2020-11-09 00:37:12.495031 <I> <red_extension.c:583> Could not find Extension at position 0

2020-11-09 00:37:12.495511 <I> <red_extension.c:583> Could not find Extension at position 1

2020-11-09 00:37:12.501818 <I> <redapid.c:312> Connected to RED Brick API Daemon

2020-11-09 00:37:12.583135 <I> <network.c:304> Added new client (N: 127.0.0.1:35308, T: plain-socket, H: 24/24, B: 0, P: 0, A: disabled)

2020-11-09 00:37:13.106176 <I> <red_stack.c:568> SPI stack slave discovery done. Found 1 slave(s) with 1 UID(s) in total

2020-11-09 00:37:13.503999 <W> <network.c:446> Received enumerate-connected callback (uid: KcD), dropped 1 now stale pending request(s)

2020-11-09 00:37:39.435761 <I> <network.c:304> Added new client (N: g_red_brick, T: file, H: 25/25, B: 0, P: 0, A: disabled)

2020-11-09 00:37:39.435928 <I> <red_usb_gadget.c:118> Connected to RED Brick USB gadget

 

wobei "KcD" die UID meines Rotary Encoders 2.0 ist.

Leider weiss ich nicht, wo der RED-Brick den printf-Befehl ausgibt. Deshalb habe den Wert auf dem LCD128x64 ausgeben lassen.

Auch da liefert die Funktion den 0 als return-value, wenn ich das Dosiersystem ohne den PC starte.

 

Ich hoffe, diese Infos bringen etwas Licht ins Dunkel.

 

Dann habe ich noch zwei kleine Probleme:

1. Im Moment ist der RED-Brick nicht in der Lage das C/C++-Update durchzuführen. Er meldet zwar nach Ewigkeiten (>45 min) dass das Update erfolgreich war. Es ist aber nach wie vor Version 2.1.30 installiert. Suche ich dann erneut nach Updates, dann meldet er wieder, dass eine neue Version vorhanden ist. Das Spiel beginnt von vorn.

2. Wenn ich ein LCD-Display von Joy-It anschliesse (nur HDMI, nicht USB für touch), dann sehe das Farbenspiel, egal ob ich zuerst den Brick oder das Display einschalte. Erst wenn ich den HDMI-Anschluss trenne und neu verbinde, erscheint der Linux-Desktop und das blaue TF.

 

Hat da jemand eine Idee?

 

Gruss

Uwe

 

 

 

Link zu diesem Kommentar
Share on other sites

Aus dem Log sehe ich folgendes: Dein Programm startet sehr schnell nachdem Brick Daemon und RED Brick API Daemon gestartet sind (das ist die Zeile mit "Added new client (N: 127.0.0.1..."). Der Brick Daemon resettet anscheinend erst danach den Master Brick, weshalb dieser "vergisst" dass die Bricklets angeschlossen sind und an allen Ports neu anfragt. Das Rotary Encoder Bricklet meldet sich dann ("Received enumerate-connected callback (uid: KcD)") was der Brick Daemon als "Das Bricklet wurde neu angesteckt, ich werfe alle alten Anfragen weg weil die jetzt keinen Sinn mehr ergeben" behandelt. Eine Anfrage (vermutlich die Callback-Konfiguration) wurde dann verworfen.

Mich wundert allerdings, warum du dann trotzdem 0, also keinen Fehler zurückbekommst. Hast du da eventuell einen Bug in der Anzeige auf dem LCD? Mit der Zahl-zu-String-Konvertierung? Du kannst den Rückgabewert, wenn du ihm mit printf ausgibst dann mit dem Brick Viewer sehen:

image.png

Wenn du die stdout.log anklickst solltest du die Ausgaben deines Programms sehen können.

Als grundlegende Frage: Behebt sich dein Problem, wenn du in der main (bevor du irgendetwas anderes machst) ein paar Sekunden wartest?

Link zu diesem Kommentar
Share on other sites

6 minutes ago, rtrbt said:

Was der Brick Daemon als "Das Bricklet wurde neu angesteckt, ich werfe alle alten Anfragen weg weil die jetzt keinen Sinn mehr ergeben" behandelt. Eine Anfrage (vermutlich die Callback-Konfiguration) wurde dann verworfen.

Das bedeutet aber nicht, dass alleine dadurch die Antwort verloren gehen kann, sondern nur, dass, falls die Antwort ankommt, sie jetzt per Broadcast an alle geschickt würde, statt gezielt an den Anfragenden.

Link zu diesem Kommentar
Share on other sites

Guten Morgen.

Vielen Dank für die Rückmeldungen.

Zum Tipp mit dem Warten in der main():

Habe einfach eine for-Schleife mit printf("a") eingebaut.

Mit dieser Schleife funktioniert es, d.h. das Programm reagiert auf den Encoder, auch wenn der RED-Brick nicht an einem Computer hängt.

Welche Infos wären noch nützlich für die Ursachenforschung?

 

Link zu diesem Kommentar
Share on other sites

Es passiert da denke ich folgendes: Dein Programm wird gestartet, aber brickd hat noch nicht alle Bricklet gefunden. Dadurch sendet dein Programm jetzt die rotary_encoder_v2_set_count_callback_configuration Anfrage, diese wird aber in brickd verworfen, weil die UID noch nicht bekannt ist. Deswegen hilft es auch wenn du in deinem Programm am Anfang kurz wartest, weil du dann erst rotary_encoder_v2_set_count_callback_configuration aufrufst, wenn brickd alle Bricklets gefunden hat.

Im Fehlerfall sollte rotary_encoder_v2_set_count_callback_configuration aber nicht 0 sondern -1 (Timeout) ausgeben, das verwundert mich etwas.

Das eigentliche Problem ist, dass dein Programm gestartet wird bevor brickd bereit ist. Das Problem kannst du durch kurzes Warten in deinem Programm umgehen, ich nehme das aber auch mal auf die TODO Liste, das zu verbessern, so dass Programm nicht mehr zu früh gestartet werden.

Link zu diesem Kommentar
Share on other sites

On 11/9/2020 at 8:01 PM, uwew said:

1. Im Moment ist der RED-Brick nicht in der Lage das C/C++-Update durchzuführen. Er meldet zwar nach Ewigkeiten (>45 min) dass das Update erfolgreich war. Es ist aber nach wie vor Version 2.1.30 installiert. Suche ich dann erneut nach Updates, dann meldet er wieder, dass eine neue Version vorhanden ist. Das Spiel beginnt von vorn.

Das sollte inzwischen gefixt sein, auf dem Download-Server lag eine falsche Test-Datei die dazu führte, dass der Update-Check durcheinander kam.

On 11/9/2020 at 8:01 PM, uwew said:

2. Wenn ich ein LCD-Display von Joy-It anschliesse (nur HDMI, nicht USB für touch), dann sehe das Farbenspiel, egal ob ich zuerst den Brick oder das Display einschalte. Erst wenn ich den HDMI-Anschluss trenne und neu verbinde, erscheint der Linux-Desktop und das blaue TF.

Wie sieht das Farbenspiel genau aus? Mach am besten mal ein Foto. Was passiert wenn du den Desktop siehst und dann den RED-Brick z.B. über Brick Viewer rebootest (dabei aber nicht Display oder RED-Brick vom Strom trennst)?

Link zu diesem Kommentar
Share on other sites

Problem Nr. 1 ist erledigt - ich habe die aktuelle Version des Brick-Viewers draufgespielt🙂.

Zu Problem Nr. 2, Farbenspiel:

  • Das Joy-It-Display ist vollflächig weiss, rot, grün, blau, dunkel im 2-sec-Abstand, wenn beim Einschalten das Joy-It-Display über den HDMI-Port mit dem RED-Brick verbunden und eingeschaltet ist. Trenne ich dann HDMI-Verbindung, so erscheint beim erneuten Einstecken des HDMI-Kabels der gewohnte TF-Desktop.
  • Boote ich den RED-Brick über den grünen Kreis unten rechts auf dem Desktop, gelange ich zum erwähnten Farbenspiel.
  • Starte ich den Brick-Viewer auf dem RED-Brick und führe ich dort einen Reboot durch komme ich zum gleichen Ergebnis.
  • Abhilfe schafft nur das Trennen der Verbindung zwischen Joy-It und RED-Brick.

.An dieser Stelle muss ich mal ein herzliches Dankeschön für die kompetente und schnelle Hilfestellung loswerden.

 

 

 

 

Link zu diesem Kommentar
Share on other sites

Zu deinem Displayproblem: Ich fürchte das ist eine Inkompatibilität zwischen Display und Prozessor und Kernel des RED-Bricks. Erfahrungsgemäß gibt es manche Displays, die nie funktionieren, wenn man das Kabel nachträglich ansteckt, und andere die das zwingend brauchen. Vermutlich triffst du mit deinem Display den zweiten Fall. Wenn du nicht gerade ein anderes Display verwenden willst, wird man da nicht viel machen können, sorry.

Link zu diesem Kommentar
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Gast
Reply to this topic...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Clear editor

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...