Forum: Mikrocontroller und Digitale Elektronik seltsames Verhalten meines RP Pico


von Theo H. (theo_rp_pico)


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.

von Thomas W. (datenreisender)


Lesenswert?

Falls Du einen zweiten Pico hast, kannst Du den zweiten Pico als 
Debug-Probe benutzen: 
https://www.raspberrypi.com/documentation/microcontrollers/pico-series.html#swd

Oder Du kaufst eine Pico-Probe.

von Norbert (der_norbert)


Lesenswert?

Es steht zu befürchten, dass:
1
bool tCallback()
eine ISR ist. Und wenn dort drin globale Variablen modifiziert werden
1
bool led_status = false;
2
bool nix_schalter = false;

wird das Hauptprogramm dies ohne weitere sachdienliche Anweisungen wohl 
gar nicht erst mitbekommen.

von Theo H. (theo_rp_pico)


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.

von Norbert (der_norbert)


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.

von Thomas W. (datenreisender)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.