seltsames Verhalten meines RP Pico

OP #8035780
Lesenswert?

Servus, bin neu hier im Forum und habe ein Problem mit der Programmierung meines RP pico. Ich will die Timerfunktion verstehen. Sie soll ja den Prozessor nicht blockieren wie dir Sleepfunktion. Dazu habe ich ein Program geschrieben bzw zusammenkopiert, das eine Led 2 Sekunden leuchten läßt und währenddessen ein Thermometer Und Feuchtigkeitsmesser (dht11) ausliest. Hier der Code:

1
#include <stdio.h>
2
#include <math.h>
3
#include "pico/stdlib.h"
4
#include "hardware/gpio.h"
5

6
const uint LED_PIN = PICO_DEFAULT_LED_PIN;
7
//const uint DHT_PIN = 15;
8
const uint DHT_PIN = 0;
9
const uint MAX_TIMINGS = 85;
10
bool led_status = false;
11
bool nix_schalter = false;
12
struct repeating_timer timer;  //structure declaration
13
typedef struct {
14
    float humidity;
15
    float temp_celsius;
16
} dht_reading;
17

18

19
bool tCallback( repeating_timer_t *timer){
20
  led_status = !led_status;
21
    gpio_put(LED_PIN, led_status);  
22
  printf("das ist der nix_schalter am Eingang %i, \n ",nix_schalter);
23
  nix_schalter = false;
24
  printf("das ist der nix_schalter am Ausgang %i, \n",nix_schalter);
25
  return true;
26
}
27

28

29
void read_from_dht(dht_reading *result);
30
uint DHT11_Read_Data(dht_reading *result);
31
int main() {
32
  uint32_t i,k, l;
33
  i=k=l=0;
34

35
// Pico pios initialisieren  
36
    stdio_init_all();
37
    gpio_init(LED_PIN);
38
    gpio_init(DHT_PIN);
39
    gpio_set_dir(LED_PIN, GPIO_OUT);
40
  gpio_put(LED_PIN, false);
41
  sleep_ms(10000);          // Warten, daß ich nach dem Start das Terminal aufmache
42

43
  printf("das kommt jetzt %d \n",i);
44
    i++;
45
//  Sensoren auslesen
46
  dht_reading reading;
47
    DHT11_Read_Data(&reading);
48
    float fahrenheit = (reading.temp_celsius * 9 / 5) + 32;
49
    printf("Humidity = %.1f%%, Temperature = %.1fC (%.1fF)\n",reading.humidity, reading.temp_celsius, fahrenheit); 
50

51
//  Timer starten
52
  add_repeating_timer_ms(2000,tCallback,NULL,&timer);  //starting the timer
53
    l++;
54
//    Schleife um die Sensoren nach dem Timeraufruf einmal auszulesen
55
    while(1) {
56
    printf("das ist der nix_schalter am Anfang der Whileschleife %i, \n",nix_schalter);
57
    l++;
58
//    nix_schalter abfragen, damit nur einmal ausgelesen wird
59
    if (!nix_schalter) {
60
    printf("das kommt jetzt %d, %d, %f, %i, \n",k,l);  // Ausgabe um zu sehen was er alles so gemacht hat
61
    k++;
62
    i++;
63
        dht_reading reading;
64
        DHT11_Read_Data(&reading);
65
        float fahrenheit = (reading.temp_celsius * 9 / 5) + 32;
66
        printf("Humidity = %.1f%%, Temperature = %.1fC (%.1fF)\n",reading.humidity, reading.temp_celsius, fahrenheit); 
67
      }
68
    l=l+1;
69
    nix_schalter = true;  // nix_schalter auf true setzen, damit er beim nächsten Durchlauf die Sensoren nicht ausliest.
70
    i++;
71
    }
72
}

Das ganze Drumrum um das Auslesen der Sensoren hab ich nicht angehängt Die meisten Zähler und print Befehle hab ich nur eingefügt um zu sehen wann er was macht bzw. nicht macht. Das Problem erscheint nach dem Aufruf von "add_repeating_timer_ms" in Zeile 52. Wenn ich die Zeile prinf... (Zeile 56) habe durchläuft es die Whileschleifen sauber und wenn nicht (auskommentiert oder gelöscht) dann nicht! Ich will aber den ganzen Mist den er mir dann schickt nicht haben und ich will das Verhalten verstehen. Zum Schluß: bin mir nicht sicher ob ich die Ausgaben richtig eingebunden habe, hab aber nix gefunden wie die formatiert werden sollten.

Und jetzt erst mal vielen Dank für Antworten. Das ist die Ausgabe mit Zeile 56: das kommt jetzt 0

Humidity = 56.0%, Temperature = 20.0C (68.0F)

das ist der nix_schalter am Anfang der Whileschleife 0,

das kommt jetzt 0, 2, 0.000000, 536876024,

Humidity = 0.0%, Temperature = 0.0C (32.0F)

das ist der nix_schalter am Anfang der Whileschleife 1,

das ist der nix_schalter am Anfang der Whileschleife 1, ...ca 33000 mal dann das ist der nix_schalter am Eingang 1,

das ist der nix_schaltdas ist der nix_schalter am Anfang der Whileschleife 1,

das kommt jetzt 1, 33390, 0.000000, 0,

Humidity = 56.0%, Temperature = 20.0C (68.0F)

das ist der nix_schalter am Anfang der Whileschleife 1,

das ist der nix_schalter am Anfang der Whileschleife 1, ... usw

Hier die Ausgabe ohne Zeile 56: das kommt jetzt 0

Humidity = 55.0%, Temperature = 20.0C (68.0F)

das kommt jetzt 0, 2, 0.000000, 536876024,

Humidity = 0.0%, Temperature = -infC (-infF)

das ist der nix_schalter am Eingang 1,

das ist der nix_schalter am Ausgang 0,

das ist der nix_schalter am Eingang 1,

das ist der nix_schalter am Ausgang 0, ... usw.

OP #8035802
Lesenswert?

Danke für die Antworten, an Datenreisender: hab nen 2. pico, muß mir aber erst noch Kabel besorgen. Ein Pico-probe schadet sicher auch nix, wenn ich mir den zuleg. Das wird also noch etwas dauern, werd ich aber auf jeden Fall angehen.

an der_Norbert: "led_status" ist nicht das Problem, die Leds werden geschaltet. "nix_schalter" wird geschaltet, wenn die ominöse printf-Zeile drin ist, und nicht, wenn sie nicht drin ist. Ich versteh die Abhängigkeit von dem printf - Kommando nicht.

#8035806
Lesenswert?

Theo H. schrieb:

"nix_schalter" wird geschaltet, wenn die ominöse printf-Zeile drin ist, und nicht, wenn sie nicht drin ist.

Das ist eine (verständliche) Fehlannahme. "nix_schalter" wird in der ISR geschaltet, aber das Hauptprogramm bekommt es nicht mit weil es mit einer, nennen wir es mal ›lokalen, temporären Kopie‹ arbeitet!

Wenn es dir nichts ausmacht (Achtung Insiderwitz) knietief durch Blut zu waten, dann suche im Forum mal nach volatile.

Gast #8035812
Lesenswert?

Theo H. schrieb:

an Datenreisender: hab nen 2. pico, muß mir aber erst noch Kabel besorgen. Ein Pico-probe schadet sicher auch nix, wenn ich mir den zuleg. Das wird also noch etwas dauern, werd ich aber auf jeden Fall angehen.

Drei Kabel reichen: https://pip-assets.raspberrypi.com/categories/610-raspberry-pi-pico/documents/RP-008276-DS-1-getting-started-with-pico.pdf?disposition=inline

Seite 17 zeigt Dir die Verkabelung.

an der_Norbert: "led_status" ist nicht das Problem, die Leds werden geschaltet. "nix_schalter" wird geschaltet, wenn die ominöse printf-Zeile drin ist, und nicht, wenn sie nicht drin ist. Ich versteh die Abhängigkeit von dem printf - Kommando nicht.

Norbert wollte Dir den type qualifier "volatile" nahelegen: Deine Callback ist eine ISR (ich nehme mal an), und da kann alles moegliche passieren (https://de.wikipedia.org/wiki/Volatile_(Informatik)). Es kann auch sein, dass durch die Optimierung des Compilers die Reihenfolge der Kommandos veraendert wurde.

OP #8036032
Lesenswert?

So Danke an alle, es funktioniert. Habe die zwei Variablen als volatile deklariert und schon geht's. Bin in C nur etwas mehr als oberflächlich Vertraut und da fehlt's halt schon an einigen Stellen aber man kann ja lernen.

Danke

Theo

P.S. habe gerade festgestellt es funktioniert nur so lala, sprich da gibt es Aussetzer. Aber da muß ich erst mal versuchen das selber zu lösen bevor ich Euch da weiter belästige.

#8036041
Lesenswert?

Verwendest Du beide Cores des RP2040?

Wenn ja, dann siehst Du evtl. die Effekte von nebenläufiger Ausführung.

Das Thema ist leider gar nicht so einfach sauber zu lösen. Entweder weiß man genau was der verwendete Core in der Lage ist zu tun und beschränkt sich auf ganz klar definierte Operationen (also z.B. nur Core1 schreibt Variable X und die darf nur ein uint32_t sein) oder man beginnt über Locking und Critical Sections nachzudenken.

Wenn das mehr als ein paar sehr wenige Stellen werden, empfiehlt es sich über ein RTOS nachzudenken - das muss man zwar einmal einbinden und initialisieren, bietet einem dann aber praktische Mechanismen um mit solchen Problemen gut umgehen zu können.

Beispiele für RTOSse, falls es Dich interessiert:

FreeRTOS https://www.freertos.org/Documentation/01-FreeRTOS-quick-start/01-Beginners-guide/01-RTOS-fundamentals

ChibiOS https://www.chibios.org/dokuwiki/doku.php?id=chibios:documentation:books:rt:start

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren