Forum: Mikrocontroller und Digitale Elektronik ESP32 Sensor+Servo


von Andrea I. (andele)


Angehängte Dateien:

Lesenswert?

- ESP32
- 4x IR Sensor (lm393)
- 2x Servo (SG90)
- 2x DC Motoren
- 1X Adafruit 16-Kanal (PCA9685)

Hallo zusammen, habe folgendes Problem:
Versuche mit 4XSensoren und 2XServo Pan/Tilt nachzumachen, soweit 
funktionert das ohne Probleme. Jedoch wenn ich das als Webserver laufen 
lasse funktioniert das nicht ,bin am zweifeln und weiss nicht woran es 
liegt.
Das ganze ist einen kleiner roboter der über Wifi gesteuert wird und 
soll sein Kopf nach links/rechts/oben und unten bewegen je nach sensor 
aktivität.
Hoffe da kann jemand helfen.

INO sind gepackt im Anhang

von Stefan F. (Gast)


Lesenswert?

Andrea I. schrieb:
> Jedoch wenn ich das als Webserver laufen
> lasse funktioniert das nicht

Was genau funktioniert nicht?

von Andrea I. (andele)


Lesenswert?

Die reaktion der sensoren ist unterschiedlich, im Serial wird es zwar 
angezeigt aber es bewegt sich nur ein Servo, Servo1(links und rechts) 
funktioniert aber Servo2(oben und unten) nicht.

von Stefan F. (Gast)


Lesenswert?

Dann reduziere dein Programm auf ganz kleine Demos, die nur jeweils eine 
Funktion durchtesten. Wenn das klappt, baue es schrittweise zusammen, 
bis es wieder nicht funktioniert. Dann weist du, in welchem Schritt der 
Fehler steckt.

Was die vielen String-Konstanten angeht: beschäftige dich mal mit dem 
F() Makro, sonst belegst du sehr viel Platz im ohnehin knappen Stack.

von leo (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Was die vielen String-Konstanten angeht: beschäftige dich mal mit dem
> F() Makro,

Auf dem ESP32? Du sollst auch lesen, nicht nur posten.

leo

von Andrea I. (andele)


Lesenswert?

So klappt es
1
#include <Adafruit_PWMServoDriver.h>
2
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
3
#define I2C_SDA 22
4
#define I2C_SCL 21
5
6
#define SERVOMIN 1100
7
#define SERVOMAX 3000
8
9
//Sensor pins
10
const int IR_O = 39;
11
const int IR_U = 36;
12
const int IR_L = 35;
13
const int IR_R = 34;
14
15
int posA = 40;
16
int posB = 60;
17
int stepsize = 2;
18
19
void setup() {
20
  Serial.begin(115200);
21
  Wire.begin(I2C_SDA, I2C_SCL);
22
  pinMode (IR_O, INPUT);
23
  pinMode (IR_U, INPUT);
24
  pinMode (IR_L, INPUT);
25
  pinMode (IR_R, INPUT);
26
  pwm.begin();
27
  pwm.setPWMFreq(50);
28
}
29
30
void loop() {
31
  bewegung();
32
}
33
34
void bewegung() {
35
  int statusSensor_O = digitalRead(IR_O);
36
  int statusSensor_U = digitalRead(IR_U);
37
  int statusSensor_R = digitalRead(IR_R);
38
  int statusSensor_L = digitalRead(IR_L);
39
40
  if (statusSensor_O == 0){
41
    Serial.println("Oben") ;
42
    posA = posA + stepsize;
43
    pwm.setPWM(4, 0, pulseWidth(posA));
44
    delay(10); 
45
    if (posA > 150){
46
      posA = 150;
47
    }    
48
  }
49
  
50
  if (statusSensor_U == 0){
51
    Serial.println("Unten") ;
52
    posA = posA - stepsize;
53
    pwm.setPWM(4, 0, pulseWidth(posA));
54
    delay(10);  
55
    if (posA < 40){
56
      posA = 40;
57
    }  
58
  }
59
  
60
  if (statusSensor_L == 0){
61
    Serial.println("Links") ;
62
    posB = posB + stepsize;
63
    pwm.setPWM(2, 0, pulseWidth(posB));
64
    delay(10);   
65
    if (posB > 120){
66
      posB = 120;     
67
    }  
68
  }
69
  
70
  if (statusSensor_R == 0){
71
    Serial.println("Rechts") ;
72
    posB = posB - stepsize;
73
    pwm.setPWM(2, 0, pulseWidth(posB));
74
    delay(10);
75
    if (posB < 10) {
76
      posB = 10;        
77
    }
78
  }
79
}
80
81
int pulseWidth(int angle){  
82
  int pulse_wide, analog_value;
83
  pulse_wide   = map(angle, 0, 180, SERVOMIN, SERVOMAX);
84
  analog_value = int(float(pulse_wide) / 1000000 * 50 * 4096);
85
  return analog_value;
86
}

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Die berechneten Werte von pulseWidth() könntest du mal seriell ausgeben 
und kontrollieren. Auch in der Funktion setMotorsXY() könnten Debug 
Meldungen dabei helfen, nachzuvollziehen, was die Funktion bzw. ob sie 
das tut, was sie soll.

Die Schleife
> while (client.connected()) { ...}
blockiert deine Loop für lange Zeit. Eventuell löst da sogar der 
Watchdog aus. Ich würde da mal mindestens ein yield() einfügen. Besser 
wäre, das Programm mittels Zustandsautomaten so umzuschreiben, dass es 
überhaupt keine blockierenden Warteschleifen hat, also auch keine 
delay().

Deine Methode, einzelne Zeichen in der String Variable "header" zu 
sammeln, halte ich für ziemlich problematisch. Damit riskierst du, den 
Heap zu fragmentieren, so dass das Ding nach kurzer Laufzeit abstürzt. 
Da dies der einzige String ist, mit dem du das machst, hast du 
vermutlich noch Glück. Komplexere Anwendungen würden Dir aber mit hoher 
Wahrscheinlichkeit auf die Nase fallen.

Lies dir dazu mal das durch: 
https://cpp4arduino.com/2018/11/21/eight-tips-to-use-the-string-class-efficiently.html
Und das: https://www.mikrocontroller.net/articles/Heap-Fragmentierung
Und das: 
https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/

von Stefan F. (Gast)


Lesenswert?

Andrea I. schrieb:
> So klappt es

Gut. Dann teste jetzt den Webserver ohne die Motoren anzusteuern. Kannst 
ja mit Textmeldungen ausgeben, welche die Funktion bestätigen.

von Andrea I. (andele)


Lesenswert?

Danke Stefan für den Ansatzt, Habe ich alles ausprobiert und dies step 
by step eingebaut, der Webserver läuft ,habe extra noch drei Buttons 
eingebaut um das über Wifi zu bedienen, hab auch ein sensor nach den 
anderen abgebaut bzw. vertauscht. Die bewegungen Links+Rechts klappt nur 
halt Oben+Unten leider nicht.
Du sagst mit der > while (client.connected()) { ...} könnte konflikte 
geben?
wie würdest du das machen bzw. wie könnte man das machen?

von Stefan F. (Gast)


Lesenswert?

Andrea I. schrieb:
> wie würdest du das machen bzw. wie könnte man das machen?

Füge da einen yield() ein oder delay(1) ein, dadurch wird etwas Zeit an 
das Betriebssystem abgegeben.

Und versuche mal, die String Variable durch ein char[] mist fester Größe 
zu ersetzen. Dann musst du natürlich auch die C Funktionen der 
<string.h> benutzen, die mit char[] operieren.

von Andrea I. (andele)


Lesenswert?

So habe ich das verstanden
1
    while (client.connected()) { 
2
        delay(1);
3
      if (client.available()) {.........
------------------------------------------
1
//statt
2
client.println
3
4
//das?
5
const unsigned char client[]PROGMEM = {........

von Stefan F. (Gast)


Lesenswert?

Das mit dem Delay ist gut. Deine Printlines sollst du mit dem F() Makro 
machen.

client.println(F("was auch immer"));

Ist viel kompakter, als mit PROGMEM herum zu fummeln.

von Andrea I. (andele)


Lesenswert?

- delay blockiert die bedienung für die DC-Motoren.
- client.println(F("was auch immer")); habe es abgeändert jedoch sind 
keine änderungen bei den sensoren.
1
    while (client.connected()) { 
2
      delay(1);
3
      if (client.available()) {

von Stefan F. (Gast)


Lesenswert?

Baue ganz viele debug Meldungen ein um den Ablauf und die Variablen zu 
kontrollieren.

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.