Forum: Mikrocontroller und Digitale Elektronik ESP8266 PWM Pin4


von Schorsch Z. (schorsch_z)


Lesenswert?

Hi, kann man den Pin4 verwenden um ein PWM Feedback von der Wilo 
Umwälzpumpe zu bekommen?

frequency = 150
solarpump = PWM(Pin(5), frequency)
pwminput = PWM(Pin(4), 75)

Das Senden funktioniert, aber ich bekomme keine Antwort auf Pin4:

PWM(4, freq=75, duty=0)
399
PWM(4, freq=75, duty=0)

von Steve van de Grens (roehrmond)


Lesenswert?

Board, Framework, PWM Bibliothek, Schaltplan, Quelltext?

von Schorsch Z. (schorsch_z)


Lesenswert?

Board: Nodemcu 12e
http://cms.media.wilo.com/cdndoc/wilo429191/4683951/wilo429191.pdf
Micropython Quellcode:

import uos, machine, esp, gc, webrepl, network, socket, ure, time
import onewire, ds18x20
from machine import PWM, Pin
from umqttsimple import MQTTClient
import ubinascii
from time import sleep

mqtt_server = '192.168.178.23'
client_id = ubinascii.hexlify(machine.unique_id())
topic_sub = b'heatp/solar'
topic_sub2 = b'heatp/pump'
topic_pub = b'heatp/heizraum'
#solartemp = -199
#pumpvalue = 1022
last_message = 0
message_interval = 5
counter = 0
frequency = 150
solarpump = PWM(Pin(5), frequency)
pwminput = PWM(Pin(4), 75)

def sub_cb(topic, msg):
  global solartemp
  global pumpvalue
  print(topic, msg)
  if topic == topic_sub:
     solartemp = int(msg.decode('utf-8'))
     print(solartemp)
  if topic == b'heatp/pump':
     pumpvalue = int(msg.decode('utf-8'))


def connect_and_subscribe():
  global client_id, mqtt_server, topic_sub
  client = MQTTClient(client_id, mqtt_server)
  client.set_callback(sub_cb)
  client.connect()
  client.subscribe(topic_sub)
  client.subscribe("heatp/pump")
  print('Connected to %s MQTT broker, subscribed to %s topic' % 
(mqtt_server, topic_sub))
  return client

def restart_and_reconnect():
  print('Failed to connect to MQTT broker. Reconnecting...')
  time.sleep(5)
  machine.reset()

try:
  client = connect_and_subscribe()
except OSError as e:
  restart_and_reconnect()

while True:
  try:
    client.check_msg()
    if (time.time() - last_message) > message_interval:
      msg = b'Hello #%d' % counter
      last_message = time.time()
      print(last_message)
      client.publish("heatp/ip169", msg)
      counter += 1
    if 3>4: #4 < stemp < 32:
      solarpump.duty(0)
    else:
      try: pumpvalue
      except NameError: x = 777
      else:
       print(pumpvalue)
       print(pwminput)
       solarpump.duty(pumpvalue)
       sleep(0.5)
  except OSError as e:
    restart_and_reconnect()

von Steve van de Grens (roehrmond)


Lesenswert?

In der Doku steht nichts von PWM Eingabe, nur Ausgabe ist vorgesehen.
https://docs.micropython.org/en/latest/esp8266/tutorial/pwm.html

Wenn du was anderes benutzt, dass mache konkrete Angaben dazu. Hast du 
dich vergewissert, dass das PWM Signal vorhanden ist und plausibel ist?

von Schorsch Z. (schorsch_z)


Lesenswert?

Ja, die Antwort sieht auf dem Oszilloskop einwandfrei aus.

Danke für Deine Antwort, das wäre aber schade, wenn ein so mächtiger 
Chip wie der ESP8266 kein PWM Signal als Input auswerten könnte.
Es muss ja nur der Duty_Cycle der am Pin anliegt, erkannt werden.
Ich könnte mir aber vorstellen, dass das Board nicht mit zwei 
verschiedenen Frequenzen umgehen kann. Die Frage warum WILO, beim 
Feedback 75Hz verwendet, stelle ich mir auch.

von Rahul D. (rahul)


Lesenswert?

Schorsch Z. schrieb:
> das wäre aber schade, wenn ein so mächtiger
> Chip wie der ESP8266 kein PWM Signal als Input auswerten könnte.

Dafür hat er aber Fähigkeiten, die andere Controller nicht haben, die 
PWMs vermessen können...

Der erste Blick sollte ins Datenblatt gehen:
https://www.espressif.com/sites/default/files/documentation/0a-esp8266ex_datasheet_en.pdf
Kapitel 4.:"Peripheral Interface"
Da steht nur, dass er vier PWMs erzeugen kann, aber nicht, dass sie auch 
einlesen kann. Der hat vermutlich schon mit dem WLAN-Gedöns genug um die 
Ohren.

Man könnte einen AVR (oder ähnliches) nehmen, mit dem die PWN per 
Input-Capture-Unit messen und dann UART, I²C oder SPI an den ESP 
übertragen.

von Steve van de Grens (roehrmond)


Lesenswert?

Rahul D. schrieb:
> Da steht nur, dass er vier PWMs erzeugen kann, aber nich

Selbst dass ist eigentlich gelogen. Der Chip hat keinerlei PWM Hardware. 
Deswegen heißt es im Datenblatt: "The functionality of PWM interfaces 
can be implemented via software programming".

Und "via software programming" ist insofern problematisch, dass die 
Software unregelmäßig oft und unterschiedlich lange unterbrochen wird, 
um die WLAN Schnittstelle zu bedienen. Die Ergebnisse werden 
dementsprechend ungenau. Sieht man bei PWM Dimmern schön daran, dass die 
Lichter flackern. Mal mehr, mal weniger.

von Rahul D. (rahul)


Lesenswert?

Steve van de Grens schrieb:
> Selbst dass ist eigentlich gelogen.

Ich habe das Datenblatt im Gegensatz zu anderen zumindest überflogen... 
;)

von Schorsch Z. (schorsch_z)


Lesenswert?

OK, ich werde jetzt versuchen die 75Hz mit dem AD Pin zu analysieren, 
bei 10-bit Auflösung, sollte das ja keinerlei Problem sein, oder.
Also ein Software-Oszilloskop:
https://espressif-docs.readthedocs-hosted.com/projects/esp-faq/en/latest/software-framework/peripherals/adc.html

von Steve van de Grens (roehrmond)


Lesenswert?

Die Aufgabe des Programmierers ist, Wünsche mit der verfügbaren Hardware 
und Software in Einklang zu bringen. Einfach irgendwas hin zu schrieben 
und auf Glück hoffen, ist keine funktionierende Arbeitsmethode.

Von PWM Eingabe steht nirgendwo etwas. Nicht im Datenblatt, nicht der 
Anleitung von Micropython, nicht in der Anleitung vom großen Python und 
auch in keinem Diskussionsforum.

Schorsch, wo hast du das her?:
1
pwminput = PWM(Pin(4), 75)
2
print(pwminput)

> Ich könnte mir aber vorstellen, dass das Board nicht mit zwei
> verschiedenen Frequenzen umgehen kann

Beim Arduino Framework gibt es diese Einschränkung tatsächlich. Sie 
kommt daher, dass dort das PWM Signal in einem Interrupt-Handler per 
Software erzeugt wird (geht ja nicht anders) und es nur einen Timer 
gibt, der dazu taugt.

So viel zum Thema "mächtig". Was den Funktionsumfang angeht, ist der 
Chip alles andere als mächtig. Der kann ja nicht nicht einmal aus dem 
Ruhezustand aufwachen, ohne neu zu booten. Sorry, aber ich glaube zu 
vertraust da zu sehr den wohlwollenden Superlativen von Espressifs 
Marketing.

Damit du in Zukunft nicht noch öfter auf falsche Erwartungen herein 
fällst empfehle ich dir, diese Seite zu lesen: 
http://stefanfrings.de/esp8266/index.html

Und lass dir nicht einreden, dass die zahlreichen ESP32 Varianten als 
Nachfolger ohne Mängel seien. Da ist auch nicht alles Gold, was glänzt.

von Rahul D. (rahul)


Lesenswert?

Schorsch Z. schrieb:
> OK, ich werde jetzt versuchen die 75Hz mit dem AD Pin zu analysieren,
> bei 10-bit Auflösung, sollte das ja keinerlei Problem sein, oder.

Was hat die ADC-Auflösung mit einem genauen Timing (was für eine 
PWM-Vermessung reelvant sein sollte) zu tun?

Würde man den ESP-ADC kontinuierlich messen lassen ("adc_read_fast()"), 
könte man kein WiFi mehr benutzen (Punkt 4 im von die geposteten 
Dokuments).

Edit:
Vielle geht das damit:
https://esphome.io/components/sensor/pulse_width.html

> pwminput = PWM(Pin(4), 75)
Erscheint mir nicht wirklich zielführend zu sein.
Ich kann mich aber auch irren, da ich eine Aversion gegen Python habe 
(und da schimpfen andere über Arduino...)

: Bearbeitet durch User
von Steve van de Grens (roehrmond)


Lesenswert?

Schorsch Z. schrieb:
> ich werde jetzt versuchen die 75Hz mit dem AD Pin zu analysieren,
> bei 10-bit Auflösung, sollte das ja keinerlei Problem sein,

Wenn du mit bis zu 20% Abweichung vom richtigen Wert leben kannst, dann 
kann das klappen. Du musst dabei aber das WLAN aus schalten (was einen 
Neustart erfordert), sonst ist er noch ungenauer.

von Steve van de Grens (roehrmond)


Lesenswert?

Rahul D. schrieb:
> Was hat die ADC-Auflösung mit einem genauen Timing (was für eine
> PWM-Vermessung reelvant sein sollte) zu tun?

Ich denke, er will das PWM Signal mit einem Tiefpass in eine analoge 
Spannung umwandeln, und diese dann messen.

von Rahul D. (rahul)


Lesenswert?

Steve van de Grens schrieb:
> Ich denke, er will das PWM Signal mit einem Tiefpass in eine analoge
> Spannung umwandeln, und diese dann messen.

kommt mir bekannt vor...
Also ein digitales Signal analogisieren um es dann in ein digitales zu 
wandeln.
Das hat ein Kollege auch mal gemacht, weil ihm Modbus zu kompliziert 
war.
Man kann natürlich vor der Auswahl der Hardware schon mal auflisten, was 
man am Ende alles haben will.

von Schorsch Z. (schorsch_z)


Lesenswert?

Ja, es geht leider nur über den Tiefpass Umweg, da nur das pyboard die 
elegante Methode "ADC.read.timed()" zur Verfügung stellt und das ADC 
sample in einen Buffer liest, der dann ausgewertet werden kann.
Ich habe jetzt nur die Möglichkeit mit 25% Ungenauigkeit zu leben, oder 
für einen DI Pin einen buffer zu implementieren um über das timing die 
Pulsweite zu analysieren. Aber wer weiss wie ungenau das dann wieder 
sein wird? NUr gut dass das Board nur 6 Euro gekostet hat. Eventuell 
steige ich noch auf einen teurere Hardware um...

von Rahul D. (rahul)


Lesenswert?

Schorsch Z. schrieb:
> Ja, es geht leider nur über den Tiefpass Umweg, da nur das pyboard die
> elegante Methode "ADC.read.timed()" zur Verfügung stellt und das ADC
> sample in einen Buffer liest, der dann ausgewertet werden kann.

Zitat aus der micropython-Doku:
"ADC.read_timed(buf, timer)

    Read analog values into buf at a rate set by the timer object.

    buf can be bytearray or array.array for example. The ADC values have 
12-bit resolution and are stored directly into buf if its element size 
is 16 bits or greater. If buf has only 8-bit elements (eg a bytearray) 
then the sample resolution will be reduced to 8 bits.

    timer should be a Timer object, and a sample is read each time the 
timer triggers. The timer must already be initialised and running at the 
desired sampling frequency.

    To support previous behaviour of this function, timer can also be an 
integer which specifies the frequency (in Hz) to sample at. In this case 
Timer(6) will be automatically configured to run at the given 
frequency."

Woher kommt das Timer-Objekt, wenn der Controller nur den Watchdog als 
Timer besitzt?

von Εrnst B. (ernst)


Lesenswert?

Schorsch Z. schrieb:
> Eventuell
> steige ich noch auf einen teurere Hardware um...

Oder auf billigere. Das ganze PWM erzeugen&einlesen macht ein kleiner 
AVR problemlos, und kann auch per UART/I²C/SPI mit dem ESP 
kommunizieren...

von Sebastian W. (wangnick)


Lesenswert?

Schorsch Z. schrieb:
> Es muss ja nur der Duty_Cycle der am Pin anliegt, erkannt werden.

Das sollte doch aber über pin change interrupts auf dem ESP8266 möglich 
sein, oder? 
https://docs.micropython.org/en/latest/esp8266/tutorial/pins.html

LG, Sebastian

von Schorsch Z. (schorsch_z)


Lesenswert?

Das hört sich sehr gut an, das werde ich gleich mal versuchen. Vielen 
Dank!

von Schorsch Z. (schorsch_z)


Angehängte Dateien:

Lesenswert?

Hat leider nicht funktioniert, meine Abtastrate im python Script ist zu 
niedrig. Mit einem ATtiny85 und Spannungsteiler funktioniert es nun,
schade dass ich jetzt zwei Boards habe. Eine Lösung mit einem einzigen 
Board wäre mir lieber gewesen.

von Rahul D. (rahul)


Lesenswert?

Schorsch Z. schrieb:
> Eine Lösung mit einem einzigen Board wäre mir lieber gewesen.

Sowas könnte man natürlich durch eine gewisse Planung eleminieren.

von Sebastian W. (wangnick)


Lesenswert?

Schorsch Z. schrieb:
> Hat leider nicht funktioniert, meine Abtastrate im python Script ist zu
> niedrig.

Abtastrate klingt nicht nach Behandlung durch Change Interrupt ISR, oder 
irre ich mich?

LG, Sebastian

von Rahul D. (rahul)


Lesenswert?

Sebastian W. schrieb:
> Abtastrate klingt nicht nach Behandlung durch Change Interrupt ISR, oder
> irre ich mich?

Man kann natürlich Pinchange-Interrupts verwenden, wenn man auch einen 
fortlaufenden Timer hat. Gibt's sowas (einen Timer) beim ESP?

von Schorsch Z. (schorsch_z)


Lesenswert?

Ja, es stehen zwei Hardwaretimer zur Verfügung, aber damit kenne ich 
mich zu wenig aus...

von Rainer W. (rawi)


Lesenswert?

Schorsch Z. schrieb:
> NUr gut dass das Board nur 6 Euro gekostet hat. Eventuell
> steige ich noch auf einen teurere Hardware um...

Du brauchst kein teureres Board, sondern eins, dass für deine Aufgabe 
geeignet ist. Ein PWM-Signals erzeugt bzw. wertet man besser mit einem 
µC aus, der so etwas mit seiner integrierten HW unterstützt.

: Bearbeitet durch User
von Sebastian W. (wangnick)


Lesenswert?

Schorsch Z. schrieb:
> Ja, es stehen zwei Hardwaretimer zur Verfügung, aber damit kenne ich
> mich zu wenig aus...

Du könntest es auch noch mit machine.time_pulse_us(...) versuchen ...

LG, Sebastian

von Peter (pittyj)


Lesenswert?

Ich nehme einen Pin-Interrupt, einen Mikrosekunden Timer, und schon kann 
ich das ankommende Signal vermessen. Ich mache das auch einem einfachen 
NXP Arm-M0.
Warum geht so etwas auf einem ESP nicht?

von Schorsch Z. (schorsch_z)


Lesenswert?

Dazu muss ich mit dem mikrosekunden Timmer beschäftigen, das mache ich 
jetzt mal, da mir eine Lösung mit nur einem Board wesentlich besser 
gefallen würde.
Hast Du einen Sourcecode Deiner Lösung?

von Schorsch Z. (schorsch_z)


Lesenswert?

Ja, da hast Du Recht!

Ich habe jetzt eine preiswerte Hardware gefunden, mit der ich alles auf 
einem Board realisieren kann. Ich hatte vorher nur leider keine Ahnung, 
dass der Pi Pico das alles kann:

https://github.com/GitJer/Some_RPI-Pico_stuff/tree/main/PwmIn

von Sebastian W. (wangnick)


Lesenswert?

Schorsch Z. schrieb:
> Hast Du einen Sourcecode Deiner Lösung?

Machbar ist das auf dem ESP8266 mit MicroPython schon, denke ich. 
Vielleicht so:
1
import micropython
2
micropython.alloc_emergency_exception_buf(100)
3
import time
4
from machine import Pin
5
ti = tr = tf = ton = ttot = 0
6
def pirq(p):
7
     global tc, tr,tf,ton,ttot
8
     t = time.ticks_us()
9
     if p.value():
10
         if ti:
11
             ton = (tf-tr)%0x100000000
12
             ttot = (t-tr)%0x100000000
13
         tr = t
14
         ti = 1
15
     else:
16
         tf = t
17
p4 = Pin(4,Pin.IN)
18
cb = p4.irq(pirq,Pin.IRQ_FALLING|Pin.IRQ_RISING)

Während der Berechnung von duty als ton/ttot außerhalb von pirq solltest 
du die Interrupts kurz sperren.

Dieser Code fängt allerdings noch nicht den Fall 0% Duty Cycle ab.

LG, Sebastian

von Schorsch Z. (schorsch_z)


Lesenswert?

Wow, Sebastian, Du bist ja ganz schön fit mit dem Zeug!
Da ich für die Wilo Pumpen eine einfache Lösung suche habe ich mir jetzt 
aber 10 Stück Pi Pico W bei Kaufland bestellt, da die nur 5,15 Euro 
kosten und alles von der Stange können was ich brauche:
https://datasheets.raspberrypi.com/picow/pico-w-datasheet.pdf

Ich frage mich, warum ich für meine bisherigen Projekte jemals ein 
anderes Board benutzt habe.

Das Pico W ist günstiger und wesentlich leistungsfähiger als esp8266.

Viele Grüße
Schorsch

von Sebastian W. (wangnick)


Lesenswert?

Schorsch Z. schrieb:
> alles von der Stange können was ich brauche

Die PIO-Programmierung ist allerdings auch nicht gerade ohne.

LG, Sebastian

von J. S. (jojos)


Lesenswert?

Schorsch Z. schrieb:
> Ich frage mich, warum ich für meine bisherigen Projekte jemals ein
> anderes Board benutzt habe.

du hast eine tolle Tischkreissäge, aber jetzt eine große Platte die du 
da nicht durchschieben kannst. Da ist eine Handkreissäge mit Schiene auf 
einmal viel besser. Jetzt möchtest du einen Stamm aufsägen, aber der ist 
zu dick für beide Sägen. Also muss eine Bandsäge her. Passt nicht für 
die Kurvenschnitte in der Arbeitsplatte, also noch ne Stichsäge. usw....

: Bearbeitet durch User
von Schorsch Z. (schorsch_z)


Lesenswert?

Ja, man kann kaum glauben, dass sich manche Leute dann gleich ein 
Sägewerk für 290 Euro kaufen. :-)

https://www.wolf-online-shop.de/Resol-Pumpensignalwandler-Resol-PSW-Basic-Set-Wilo-Yonos-Para-ST-15-7-0-PWM::103544.html

von Steve van de Grens (roehrmond)


Lesenswert?

Python auf einem Mikrocontroller fühlt sich für mich an wie

Brötchen kaufen mit einer schweren Transportkiste. Man braucht ein Auto, 
um die schwere Kiste zu transportieren. Und eine Garage, um das Auto zu 
laden. Und eine Werkstatt, um das Auto zu pflegen.

Unterm Strich ist mir "zu Fuß gehen mit Einkaufstüte" lieber.

: Bearbeitet durch User
von Schorsch Z. (schorsch_z)


Lesenswert?

Da geht es Dir wie mir. Ich bin auch am liebsten auf steinigen Pfaden 
unterwegs, wo man nie genau weis, was als nächstes passiert und man viel 
ausprobieren kann:
https://www.youtube.com/watch?v=_JM-e_cl4Wc&t=544s

Nur beim Programmieren halte ich es wie Walter Röhrl und möchte in 
meinen von den Maintainern bis aufs letzte optimierten "Opel Ascona 400" 
einsteigen und in Rekordzeit zum Erfolg kommen :-)

https://www.youtube.com/watch?v=Ke5PaNYKlNE

von Sebastian W. (wangnick)


Lesenswert?

Steve van de Grens schrieb:
> Python auf einem Mikrocontroller fühlt sich für mich an wie
> Brötchen kaufen mit einer schweren Transportkiste.

Hab gerade https://github.com/micropython/micropython/pull/5962 
gefunden. Die MicroPython machine.Pin change interrupts auf dem ESP8266 
können nicht "hard=True" sein, sind also sehr flatterhaft. Damit lässt 
sich die Austastung eines 75Hz-Rechtecks nicht vernünftig messen, ich 
habs probiert. Die schwere Transportkiste ist also so grob gezimmert 
dass die meisten Brötchen auf die Straße fallen :(

LG, Sebastian

von Sven L. (svenloe)


Lesenswert?

Eine PWM lässt sich sehr einfach per Software einlesen, wenn der 
Eingangsport Interrupts für fallende und steigende Flanken auslösen kann 
und ein Timer vorhanden ist. Ob das der ESP8266 kann, hab ich nicht 
nachgeschaut, aber ich nehme es an.

1. Man konfiguriert den Interrupt des Ports für steigende Flanke
2. Sobald die steigende Flanke auftritt, startet man einen Timer und 
konfiguriert den Interrupt um auf fallende Flanke
3. Sobald die fallende Flanke auftritt, speichert man den Timerwert, 
startet den Timer neu und konfiguriert den Interrupt auf steigende 
Flanke
4. Anschließend wertet man den Timer aus und hat nun die Pulsdauer des 
positiven Pulses
5. Sobald die steigende Flanke auftritt, speichert man wieder den 
Timerwert, startet den Timer neu und konfiguriert den Interrupt auf 
fallende Flanke
6. Anschließend wertet man den Timer aus und hat nun die Pulsdauer des 
negativen Pulses. Aus der Pulsdauer des positiven und negativen Pulses, 
lässt sich leicht die PWM ausrechnen.

Wenn man den Interrupt mit höchster Priorität laufen lässt, dann bekommt 
man eine sehr genaue Messung, die nur von der Genauigkeit des Timers 
abhängt.

Die Flanken der PWM dürfen nicht schneller auftreten, als die ISR 
dauert.

Falls der Eingang prellt, muss man eine Entprellung vornehmen. Entweder 
in Hardware oder in Software.

vG
Sven

von Steve van de Grens (roehrmond)


Lesenswert?

Sven L. schrieb:
> Ob das der ESP8266 kann, hab ich nicht
> nachgeschaut, aber ich nehme es an.

Interrupts und Timer sind vorhanden

> Wenn man den Interrupt mit höchster Priorität laufen lässt,
> dann bekommt man eine sehr genaue Messung

Daramn scheitert es. Das Programm wird zur Bedienung der WLAN 
Schnittstelle zu unregelmäßigen Zeitpunkten für unregelmäßige Dauer 
unterbrochen. Das hat leider höhere Prio, als die Pin Changes.

: Bearbeitet durch User
von Sebastian W. (wangnick)


Lesenswert?

Sven L. schrieb:
> Eine PWM lässt sich sehr einfach per Software einlesen, wenn der
> Eingangsport Interrupts für fallende und steigende Flanken auslösen kann
> und ein Timer vorhanden ist.

Das wurde doch alles schon hier diskutiert. Aber anscheinend noch nicht 
von allen :(

LG, Sebastian

von Schorsch Z. (schorsch_z)


Lesenswert?

Mit dem Pi Pico W, funktioniert die Vermessung bei 40% Drehzahl perfekt!
Connected to 192.168.178.23 MQTT Broker
New message on topic heatp/pump
duty = 32000
High-Flanke: 72
Low-Flanke : 39556
High-Flanke:77
Low-Flanke :39734
und so weitere...
New message on topic heatp/pump
32000
103
39537
106
39695

Nochmals Vielen Dank Sebastian!

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.