This blog sequence is also available as PDF document.
Question: How do you get a large amount of data from an ESP32 for evaluation on a PC? Our MPP finder from the Third blog sequence Provides 128 measuring tops of 4 values each per measurement, a very nice amount of wood.
Image 1: Mounted solar panel
We will take care of the answer today with the help of Micropython and Python on the PC. The bridge will be the radio suitability of the ESP32. Of course, the PC (desktop, notebook, etc.) must also have a radio interface or a LAN connection. A WLAN router is also required. Are you excited to see how that should work? Then welcome to a new episode of
Micropython on the ESP32 and ESP8266
today
The MPP data export from the ESP32 to the PC
It is about finding out which panel voltage of the MPP is reached. The panel voltage, in turn, essentially depends on the load on the module with a given radiation and modular temperature. It is important to change them or to have them better changed by the ESP32. The Buck converter from the First episode of the solar series is used together with a load resistance as a variable load and an INA219 as a measurement servant, the function of which I function in the second episode described. The recording of the measured values was the subject of the third episode. And this is how the result looks when you represent the series of measurements graphically using a calculation program. I used Libre Office for this:
Image 2: Evaluation of a series of measurements with Libre Office
Hardware
The hardware list from the first episode was supplemented by the solar panels and a resistance of 4.7Ω /2W and is identical to the line-up from the third episode. So nothing changes in the structure.
1 |
|
1 |
|
1 - 3 |
Solar panel 5V 1.5W waterproof polysilicon mini solar module |
1 |
Ina219 |
1 |
N-Canal Mosfet Irlz24 (Logic Level Gate, R On = 60mΩ) |
1 |
Transistor BC337 |
2 |
Resistance 270 Ω |
2 |
Resistance 150 Ω |
1 |
Resistance 10 kΩ |
1 - 3 |
Schottky diode 1N5817 |
1 |
Electrolytic capacitor 470µF 16V |
1 |
Electrolytic capacitor 220µF 16V |
1 |
Storage throttle 330µH 1A |
1 |
Resistance 4.7 Ω / 2W |
various |
|
1 |
|
4 |
Line strip with 6 contacts each or |
1 |
Basic board 16cm x 24cm |
The software
For flashing and the programming of the ESP32:
Thonny or
Used firmware for the ESP8266/ESP32:
The Micropython programs for the project:
SSD1306.PY Hardware driver for OLED display
oled.py API for the OLED display
ina219.py Driver module for the INA219
powerline_s.py Program for finding the MPP and radio transmission
powerline_a.py File transfer without a router
Cpython for the PC
Windows X86 MSI Installer Python 2.7 for XP
Download Python 3.11.0 Latest version (64bit) for the PC at W10 / W11
Windows Installer (64-bit) Version 3.9.13 for the PC
udp_receiver.py The UDP receiver on the PC, which runs under Python 3.9.
udp_receiver_27.py The UDP receiver on the PC, which runs under Python 2.7
Micropython - Language - Modules and Programs
To install Thonny you will find one here Detailed instructions (English version). There is also a description of how the Micropython firmware (As of December 15, 2022) on the ESP chip becomes burned
Micropython is an interpreter language. The main difference to the Arduino IDE, where you always flash entire programs, is that you only have to flash the Micropython firmware once on the ESP32 so that the controller understands Micropython instructions. You can use Thonny, µpycraft, or ESPTOOL.PY. For Thonny I have the process here described.
As soon as the firmware has flashed, you can easily talk to your controller in a dialogue, test individual commands and see the answer immediately without having to compile and transmit an entire program beforehand. That is exactly what bothers me about the Arduino IDE. You simply save an enormous time if you can check simple tests of the syntax and hardware to try out and refine functions and entire program parts via the command line before knitting a program from it. For this purpose, I always like to create small test programs. As a kind of macro, they summarize recurring commands. Whole applications then develop from such program fragments.
Autostart
If the program is to start autonomously by switching on the controller, copy the program text into a newly created blank tile. Save this file under boot.py in WorkSpace and upload it to the ESP chip. The program starts automatically the next time it the reset or switched on.
Test programs
Programs from the current editor window in the Thonny-IDE are started manually via the F5 button. This can be done faster than the mouse click on the start button, or via the menu run. Only the modules used in the program must be in the flash of the ESP32.
In between, Arduino id again?
Should you later use the controller together with the Arduino IDE, just flash the program in the usual way. However, the ESP32/ESP8266 then forgot that it has ever spoken Micropython. Conversely, any espressif chip that contains a compiled program from the Arduino IDE or AT-Firmware or Lua or ... can be easily provided with the Micropython firmware. The process is always here described.
Signals on the I2C bus
How a transmission works on the I2C bus and how the signal sequence looks, you can do in my post mammutmatrix_2_ger.pdf read. I use one there Interesting little tool, with which you can get and analyze the i2C bus signals on your PC.
You can find some information in part 3. The protection of solar cells and their interconnection are important, the protective diodes, the application of which show in illustrations 3 and 4.
The MPP finder
The tasks of the ESP32 are:
- A actuator for changing the load
- A measured value entry
- The transmission of the data to the PC
The data recorded is saved in a file on the ESP32. The files are transferred to the PC by radio with the UDP protocol and saved in a file, which can finally be evaluated with a spreadsheet. Because of the radio transmission, the program must powerline.py are modified and expanded at certain points. The circuit follows again for an overview.
The circuit
Image 3: MPP finder - circuit
I have the details and functioning of the circuit of the converter in the first episode precisely explained. According to the description, the solar panels used should deliver an output of up to 1.5W with voltages up to 6.3V. This corresponds to a current strength of up to 0.3a. With a parallel circuit of three panels, approx. 1a would be expected. In order for this current to flow when the valve is open, the load resistance must have a value below 5 ohms.
The OLED display provides information about upcoming actions and finally provides the U-P characteristic for a first assessment of the measurement.
The program powerline_s.py
In the beginning, the toolbox is filled, and I import various modules. We need that I2C-Bus for conversation with the INA219 and the OLED display, PWM For the control of the converter, and of course the module Ina219. I need the module to control the ESP32 buttons, also for the file management list, and remove them from the module OS. The function exit() Allows me to cancel the program with the flash key of the ESP32. In addition, the modules came network and socket. In the following, I assume that the PC is in a LAN with the network address 10.0.2.0 and that the WLAN router has the address 10.0.2.200. It is also required that a DHCP server is active in the LAN that can assign an IP address to the ESP32 when registering. As a rule, a DHCP server runs on the WLAN router.
From machine import Softi2c,Pin code,PWM
From time import sleep
From OLED import OLED
From Ina219 import Ina219
import buttons
From OS import list, remove
From sys import exit
import network
import socket
The ESP32 should work as a UDP client. For this, he needs access to the WLAN router, i.e. SSID and password. We also assign him an IP address and port number and announce the gateway and DNS server in the LAN. In remote is the IP of the recipient.
myssidsta="Here goes yor ssid"
Mypasssta="Here goes your password"
myip="10.0.2.240"
mygw="10.0.2.200"
mydns=mygw
myport=9009
remote=("10.0.2.241",9091)
Only values outside the "Well-Known Ports" from 0 to 1023 should be selected as port numbers, i.e. values from 1024 to 65535.
Then the preparations begin. I create an I2C bus instance with which I also instance the display object. Delete the display and set full contrast. We work in bright surroundings.
I2C=Softi2c(Pin code(22),Pin code(21))
D=OLED(I2C)
D.clearall()
D.setcontrast(255)
The measurement resistor on the INA219 bob (Break Out Board) has 100mΩ, we expect current strengths of up to 800mA. With 128 individual measurements, each corresponds to a pixel in the OLED display. The step width for the PWM values from 0 to 1024 results from division 1024 / number of steps.
shunt = 0.1 # Ohm
imax=0.8 # Ampere
steps=128 # Number of steps
step=1024/steps
The constructor of the Ina219 class demands a whole series of arguments that are up to I2C All optional keyword parameters are. Fashionboth Request the recording of bus and shunt tension, Samp4 stands for a resolution of 12 bits with 4-fold oversampling, PGA2 Put the weaker on 1/2 and Ubus16v Allows bus voltages up to 16V.
Ina=Ina219(I2C,Fashion=Ina219.Fashionboth,
bus=Ina219.Samp4,
shuntres=Ina219.Samp4,
shuntpga=Ina219.PGA2,
ubus= Ina219.Ubus16v,
Imax=imax,
Rshunt=shunt)
T is a button object on GPIO0. The flash key of the ESP32 closes against GND, so it will invert set on true. This makes the 0 to GPIO0 when the button is pressed True For the return of the method Waitfortouch(). The button gets the name to begin And the internal pull-up resistor is switched on. The PIN GPIO5 delivers the PWM signal for the actuator with a frequency of 50kHz. With a duty cycle of 1023, a level of 5V is located on GPIO5, so the BC337 switches through and pulls the gate of IRLZ24 to GND potential, which blocks the mosfet (see Image 3) and separates the load from the panel. The idle voltage is now on the panel.
T=buttons.Buttons(0,invert=True,sweater=True,Surname="Begin)
pwmpin=5
gate=PWM(Pin code(pwmpin),freq=50000,duty=1023)
The connection status to the router is returned as a number. So that you don't have to look up extra connect status a Dictionary Ready that the number translates into plain text. Dictionaries (short: dict) are in Micropython what you know in Perl or Lua as Hash. Such structures assign any object to any key. Here, this can be a string, but also a numerical value, a list, or any other object. Values can also occur several times. However, the keys must be clear. For example, Connect status [1] delivers the string "stat_connecting".
connect status = {
1000: "Stat_idle",
1001: "Stat_Connecting",
1010: "Stat_got_ip",
202: "Stat_wrong_Password",
201: "No ap found",
5: "Unknown",
0: "Stat_idle",
1: "Stat_Connecting",
5: "Stat_got_ip",
2: "Stat_wrong_Password",
3: "No ap found",
4: "Stat_Connect_Fail",
}
In order for the connection to the router to work, it is necessary to announce the Mac address of the ESP32 in station mode to the router. To do this, you have to know them yourself. The function hexmac() reads a Bytes episode from the ESP32 and formats it so that a human body can also easily decipher it. So before you establish a connection to the router, the Mac must be entered in a list there. Please consult the router's manual.
def hexmac(bytemac):
"""
The HexMac function takes the MAC address in the bytecode
opposite and forms a string for the rehabilitation
"""
MacString =""
for I in range(0,len(bytemac)): # For all byte values
MacString += hex(bytemac[I])[2:] # from position 2 to the end
IF I <len(bytemac)-1 :# Separation signs except for the last byte
MacString +="-"
return MacString
Now I define some passages that are used several times than functions. output() receives in the position parameter the first line of up to 16 characters that are output in the first line of the OLED display. With *further (up to five) other position parameters can be fed with strings. further Represents a list of the handed-over arguments that are called up in the for loop and end up on the display in the subsequent rows.
def output(first line,*further):
D.clearall()
D.writer(first line,0,0)
for Z in range(len(further)):
D.writer(further[Z],0,Z+1)
The complex function result() reads the file whose name is Surname is handed over and filters the MPP from the data. The file is fed with measured values in the measuring loop.
def result(Surname):
try:
n=0
pmax=0
around=0
IMPP=0
pulse=0
try Starts errors that can happen when reading the file. For example, if the file does not exist. The meter for the measured values and the positions for the MPP is reset and the lists for the measured values are emptied.
The wither-Structure allows access to the file to be read Surname About the file handle F, without having to explicitly close the file at the end. It is closed automatically when the wither-Block is left. The for-loop itotes via the file entries.
The lines come from the file as an ASCII sign. The method broadcast(), which is supposed to transfer the string, expects an object that builds on the buffer protocol. So I let the string be coded in bytes. That makes the method encode(). I pack the transmission process in a Try - Except construct so that in the event of an error, the program does not stop. Errors are simply ignored by the passport.
Then the line of wagon return (\ r) and line feed (\ n) is freed and output in the terminal. I have the commas replaced with decimal points and divide the line at the line points into individual values, which I have converted into numerical values so that I can apply the arithmetic comparison to it. If the current value of the performance is larger than the maximum found so far, I remember this, and with it also the values for the bus voltage and the current, as well as the PWM value. Finally, the number of values read is increased.
wither open(Surname,"R") AS F:
for Z in F:
ZS=Z.encode()
try:
S.broadcast(ZS,remote)
except:
passport
Z=Z.strip("\No")
print(Z)
Z=Z.replac(",",".")
U,I,P,Pulse=Z.split(";")
U.append(float(U))
I.append(float(I))
P.append(float(P))
Pulse.append(intimately(Pulse))
IF P[n] > pmax:
pmax=P[n]
around=U[n]
IMPP=I[n]
pulse=Pulse[n]
n+=1
Another one try captures a division by zero error that can occur if pmax Or should be the maximum of the voltage values for any reason 0.
The maximum performance is fitted into the 64-pixel display height, and the maximum voltage (= idle voltage of the module) is in the 128-pixel display width. After the display is deleted, the for loop places the points in the U-P diagram. The MPP and the associated voltage are output on the display and in the terminal, but not sent to the PC. It should only receive the pure measured value file. Additional content would disturb the evaluation. Before closing the socket, we send the text "End" so that the program on the PC knows when it can close the file with the data records received.
try:
PACKER=63/pmax
UFAKTOR=127/Max(U)
print("UFAKTOR =",UFAKTOR)
D.clearall()
for num in range(n):
POS=63-intimately(P[num]*PACKER)
X=intimately(U[num]*UFAKTOR)
#Print (Num, X, "", U [Num], "", Pos)
D.setpixel(X,POS,1)
D.writer("Umpp = {:. 2f} V".format(around),0,4)
D.writer("Pmax = {:. 2f} w".format(pmax),0,5)
print("MPP: Umpp = {:. 2f} v impp = {:. 2f} a pmax = {:. 2f} w duty = {:. 2f}% ({})".\
format(around,IMPP,pmax,\
pulse/1023*100,pulse))
S.broadcast("end",remote)
S.close()
The Except blocks provide information about any errors that may have occurred without canceling the program.
except Zerodivisor:
print ("Share by 0 - error")
D.clearall()
D.writer("Share by 0!",0,3)
D.writer("Last measurement",1,4)
D.writer("Incorrect",3,5)
except Oserror:
print("Error reading from file")
output("File error")
The function test() creates the data for a parabola with which the function result() can test. With n I hand over the serial number for the file name, which I then use the function result() hand over. In order for this to work from the command line, the program must powerline.py have run at least once.
def test(n):
F=open("power"+Str(n)+".txt","W")
for X in range(steps):
y=-(0.01587*(X-64)**2)+63.0
S="{: .2f}; 7.24; {:. 2f}; 512 \ n".format(X,y)
F.write(S)
F.close()
With the function found name() I investigate the next fact that has not yet been used. The names consist of the string "Power" and an attached serial number, as well as the expansion ".txt". The local variable free is placed on false. It indicates whether a name is available.
As long as free not True is, in the While loop with the counter n, starting at 0, a name is composed and checked whether the file can be opened to read. This is the case if the file exists with this name. Otherwise, the name is available and it will be one Oserror Exception thrown.
Except start the error. free will be on True set, the name output in the terminal and n and the name returned.
def found name():
n=0
free=False
while need free:
try:
Surname="power"+Str(n)+".txt"
wither open(Surname,"R") AS F:
passport
n+=1
except Oserror:
free=True
print(Surname)
return n,Surname
The preparation measurement that I will explain now is the connection with the router.
I have found that the Accesspoint interface of the ESP32 interferes with the regular operation when the controller is to run in station mode. That's why I create an AP interface to immediately clean it away. Then I create the station interface object and activate it.
# **************** Set up ******************
# Create network interface instance
# and activate ESP32 station mode;
# possible are either network.sta_if or network.ap_if
# Both at the same time, as in Lua or AT-BASED
# or Adruino IDE is not possible in Micropython
nic = network.WIRELESS INTERNET ACCESS(network.Ap_if)
nic.active(False) # Switch off the AP interface object safely
nic = network.WIRELESS INTERNET ACCESS(network.Sta_if) # Constructor call creates station object Nic
nic.active(True) # Turn on the object
With nic.config ('Mac') I call the MAC address of the ST interface, convert it into a sequence of plain text, and have it output in the terminal window.
Mac = nic.config('Mac') # Call base Mac address and
mymac=hexmac(Mac) # convert into a hex digit sequence
print("Mac station: \ t"+mymac+"\ n") # spend
Normally there is still no connection to the router, which is why the body of the IF structure is underway. I try to establish the connection by the method connect the SSID and the password of the router hand over. Then I ask the connection status again and end up in the While loop, which is waiting for the granting of an IP address from the router or a special DHCP server. As long as this has not happened, a point is issued in the terminal at a second distance.
IF need nic.Isconnected():
# Connect to the AP in the local network and display status
nic.connect(myssidsta, Mypasssta)
# Wait until the connection to the Accesspoint is
print("Connection status:", nic.Isconnected())
while nic.status() != network.Stat_got_ip:
print(".",end='')
sleep(1)
The connection should be built after three to 5 seconds. If this does not work, it may be because the Mac address has not been entered correctly or has not yet entered the router.
Now I have the status output in plain text and then assign my IP data specified above. This is not absolutely necessary in the client farm if the information comes from the DHCP service, but it enables us to clear filtering approved stations at the UDP server on the PC.
ifconfig() reads the configuration data for control. Terminal windows and OLED displays show the values.
print("\ nanation status:",connect status[nic.status()])
Staconf = nic.ifconfig((myip,"255.255.255.0",mygw,mydns))
Staconf = nic.ifconfig()
print("Sta-IP: \ t \ t",Staconf[0],"\ nsta-netmask: \ t",Staconf[1],"\ nsta-gateway: \ t",Staconf[2] ,sep='')
D.clearall()
D.writer(Staconf[0],0,2)
D.writer(Staconf[1],0,3)
D.writer(Staconf[2],0,4)
sleep(3)
The UDP client is set up with a few other lines. The UDP protocol is faster and easier to handle compared to TCP. It allows a bidirectional data exchange, such as an RS232 line, but does not ensure data traffic. So there is no manual bite like TCP. For example, it is not checked whether the data has arrived correctly or at all. The argument is crucial in the first line socket.sock_dgram, which is the constructor of the socket instance S is handed over to create a UDP socket.
S = socket.socket(socket.Af_inet, socket.Sock_dgram)
S.setsockopt(socket.Sol_socket,socket.So_RuseAddr,1)
S.binding(('', myport))
print("Singing on Port {} ...".format(myport))
S.set(0.1)
D.writer("Singing on {}".format(myport),1,5)
sleep(3)
The second line ensures that the same IP address can be awarded again after a restart. Then I tie the port number to the IP address allocated above. With a timeout of 0.1 seconds, I prevent the program from being transmitted during the transfer due to an incredible error. If an error occurs, I catch it with except. More on this later.
The key T serves to control the main program. In the beginning, a new measurement can be triggered. I have the information out on the display. Then stay 3 seconds to press the button. The buffer of one second ensures that the button was released. I remember the state of the buttons in measure. True stands for "button", the timeout has expired, and comes None return.
output("Flash key","For measurement","PRESS")
Measurement=T.Waitfortouch(T,delay=3)
T.Waitforrelease(T,delay=1)
Only if you are to be measured is the question of whether the existing measured value files should be deleted. If this is the case (another push of a button), I have a list of the existing files created. If the first 5 characters in the file name "Power", the file name is output and the file is deleted. This filter preserves the file Main.py that contains the program, as well as the modulus files in front of it to be deleted. Then I search for an available file name and get back the number and file name. This means that one of two actions can be carried out.
IF Measurement:
output("Flash key"," ","To the loeschen","The files")
clear=T.Waitfortouch(T,delay=3)
IF clear:
for file in list():
IF file[:5]=="power":
print(file)
remove(file)
counter,Surname = found name()
If Measurement None, then the button T is Not pressed at the beginning. This leads to the output of the measurement curve of the last measurement on the OLED display and the measured values in the terminal. In the counter is the number of the next free file name. Counter-1 So appeals to the last available measurement.
Else: # Represent the result
Surname="power"+Str(counter-1)+".txt"
result(Surname)
With Measurement even True Starts a new series of measurements. Try blocking typing errors in the file. I open a file for writing, set the PWM value to 1023 (Mosfet blocks) and the value counter to 0.
IF Measurement:
output("MEASUREMENT","Started")
mistake=False
try:
wither open(Surname,"W") AS F:
pulse=1023
n=0
As long as pulse Single measurements are carried out larger than 0. The step distance step is a flow of flow. After each measurement of pulse subtracted. pulse So is also of the type float. To use pulse as a PWM value, an integer must be made. The number of the measurement and the pulse width is displayed in the OLED display.
while pulse>=0:
intfulse=intimately(pulse)
gate.duty(intfulse)
D.writer("{}. {} ".format(n,intfulse),0,3,True)
current() and getpower() can throw an overflow exception that I am absent with Try. In this case, will be mistake on True set and the performance of the value -1.
try:
U=Ina.getbus voltage()
I=Ina.current()
P=Ina.getpower()
except Overflowerror:
U,I,P=0,0,-1
mistake=True
The measured values are composed into a string with line feed, whereby the line point serves as a separator. When reading a measured value file as a CSV file into a calculation program, this recognizes the separation of the values and can divide into different columns. In order for the calculation tool to interpret the strings as numerical values, the decimal points must be converted into commas. The method does that replac(). The string is written in the file and the pulse reduces the step width. With the end of the With block, the file is closed automatically.
S="{: .2f}; {:. 2f}; {:. 2f}; {} \ n".\
format(U,I,P,intfulse)
S=S.replac(".",",")
F.write(S)
pulse-=step
n+=1
After completing the series of measurements, I set the Duty Cycle to 1023 and separate the panel from the load. The result of the result and the treatment of any errors follow.
gate.duty(1023)
result(Surname)
IF mistake:
D.writer("Overflowerror",0,0)
except Oserror:
print("Error when writing in file")
output("File error")
Program execution outdoors
So that the program can be executed in the pampas without a PC, it must be under the name Main.py are loaded onto the ESP32. I always create one about this new file and copy the program text, here that of Powerline_S.py, in and save the new file directly on the ESP32 under the name Main.py. With every cold start or reset, the ESP32 now automatically starts with a new run.
File transfer to the PC
Well, we would have completed the transmitter of the data. We come to the recipient. With Thonny, a CPYTHON version is also installed on the PC. This is not an emaciated version like Micropython, Cpython is the much more powerful father of Micropython. But what works in Micropython is even more possible in Cpython. Well, except for those features based on the infrastructure of the controller architecture. In Cpython, for example, there are no GPIOs, no hardware timers ... Of course, CPYTHON also has the module socket. As a result, we are able to design a UDP server on the PC with the Micropython vocabulary, which receives the data from the ESP32 and packs it into a file. As soon as the data from the file of the current measurement is read out on the ESP32, you are simultaneously beamed onto the PC. It does not matter whether the PC runs under Windows or Linux.
I also have that on my Windows 10 Python release 3.8.5 Installed. It brings the IDE IDLE. There I enter the following program, which I can later start via the Windows command line or a corresponding link from the desktop. Of course, you can also edit the program with Thonny and then save it in the workspace, or another directory. In the directory in which the file is called for execution, the CVS files it generated are also stored.
I do not need to establish a network connection because the PC usually already has one. So I only import the module socket.
import socket
Then I determine the connection data of the PC, which with the console command
ipconfig -Alles (Windows command prompt)
or
Ifconfig (Linux Terminal)
can call up.
myip="10.0.1.208"
mygw="10.0.1.200"
mydns="10.0.1.1"
myport=9091
The Dict connect status and the function hexmac () you already know. They meet the same purpose on the PC as on the ESP32.
connect status = {
1000: "Stat_idle",
1001: "Stat_Connecting",
1010: "Stat_got_ip",
202: "Stat_wrong_Password",
201: "No ap found",
5: "Unknown",
0: "Stat_idle",
1: "Stat_Connecting",
5: "Stat_got_ip",
2: "Stat_wrong_Password",
3: "No ap found",
4: "Stat_Connect_Fail",
}
def hexmac(bytemac):
"""
The HexMac function accepts the MAC address in the bytecode and
forms a string for the rehabilitation
"""
MacString =""
for I in range(0,len(bytemac)): # For all byte values
MacString += hex(bytemac[I])[2:] # from the string from position 2 to the end
IF I <len(bytemac)-1 : # Separation sign except for the last byte
MacString +="-"
return MacString
The instance of the UDP socket is also nothing new.
S = socket.socket(socket.Af_inet, socket.Sock_dgram)
S.setsockopt(socket.Sol_socket,socket.So_RuseAddr,1)
S.binding(('', myport))
print("Waiting on Port {} ...".format(myport))
S.set(0.1)
The program should now ask for a file name. When executing as a name supplement .csv (Character separated value). This format is recognized by Libre Office as a table format if you want to open the file there.
Surname=input("File name:")
print("Waiting on Port",myport)
You also already know the With structure. We open the file for writing.
The While loop tries to read a data record from the receiving buffer. If there is no data record at the moment, an Oserror Exception is thrown, caused by the timeout agreed above. We start the exception with Except. If there is nothing for processing, we are waiting by doing nothing - passport.
wither open(Surname,"W") AS F:
while 1:
try:
# Message received
Rec,ADR=S.recvfoma(150)
Rec=Rec.decode()
print(Rec,end="")
IF Rec=="end":
print("\ n program ended")
print("The file",Surname,"will be closed.")
S.close()
break
Else:
F.write(Rec)
except Oserror:
passport
But if there is a message, it will be in the variable Rec shipped and the sender address according to ADR Postponed and forgotten, no answer to the ESP32 is required. Both variables are for unpacking the tuple that the method recvfoma() delivers, necessary.
The Bytes episode is decoded in a string and output in the terminal window. Because the string already contains a linefeed (\ n = line feed), I replace the automatic linefeed of the print command with an empty string.
The message consists of the text "end", then all data records were transferred and the job is canceled with a break after the socket S has been closed. This also leaves the With structure and the file handle F thus automatically closed. All lines that are not at "End" are written in the file.
Save the program text under the name now UDP_Receiver.py from. If you also create a link on the desktop, you can start the file with a double click.
Image 4: UDP-Receiver.py as a link on the desktop
Is the hardware ready for operation and is the panel connected? Then you start first UDP_Receiver.py on the PC and assign a file name with the addition .csv. Then boot the ESP32 or press the RST key there. The controller should log in to the router so that after a few seconds the connection data is displayed on the OLED display. Now initiate the measurement with the flash key. It is up to you whether you have previously measured value files deleted or not. After the series of measurements has run through, the measurement curve is generated on the display, and the data records are sparked to the PC, where they appear in the work window of the recipient program. This is ended after the measured value file has been closed. It is now ready for evaluation.
Image 5: The file has arrived
Start Libre Office (or an analogous application) and open the file menu-Open-Open.
Image 6: Open file
Image 7: Charging the measured value file
On the basis of the name expansion .cSV, Libre Office recognizes that it is a text file with a separation sign between the fields and shows the dialogue for adjusting the separation options.
At Separation options Put the hook with a semicolon - OK
Image 8: Settings Text import
Mark the columns A, B and C.
Image 9: Mark columns
Insert click on the diagram.
Image 10: Insert diagrams
Please make a choiche XY scatter diagram - Points or Points and lines
Image 11: diagram assistant
Complete.
Image 12: Finished diagram
The blue curve is the U-I characteristics. Where it bends down, the maximum of the red curve, the MPP is. Different series of measurements have shown that the MPP is around 70% of the idle voltage on the panel. In the production company, it will be the task of the actuator to adjust the converter to this point. The external influences must of course be taken into account, so it will be necessary to check the location of the MPP at certain time intervals. A device that carries out this is called an MPP tracker. A future contribution will probably deal with this topic.
A tip at the end. A LAN is rarely available in the pampas. A notebook with a WLAN card is also sufficient for an island solution.
However, the procedure requires some changes. It starts with the ESP32 now configured as an access point, which happens in two places in the program. We award an SSID and the IP of any sub-network to the ESP32. The IP of the notebook (remote) must come from the same network.
myssid="finder"
mypass="Don't"
myip="10.0.2.100"
mygw=myip
mydns=myip
myport=9091
remote=("10.0.2.240",9091)
On the notebook, you can now establish a new WLAN connection with the ESP32. This is very quick because the connection is open, so there is no password handshake. According to the current status of Micropython, a secure connection is not possible. Nevertheless, one must be specified when creating the AP interface. In order for the connection to work, the ESP32 must have been started.
The second adaptation is the establishment of an AP interface instead of the StA-Interface. Everything else remains unchanged.
# *************** AccessPoint ****************
nic = network.WIRELESS INTERNET ACCESS(network.Ap_if)
nic.active(True) # Turn on the object
#
Mac = nic.config('Mac') # # REFORE MAGE MAC address and
mymac=hexmac(Mac) # convert into a hex digit sequence
print("Mac station: \ t"+mymac+"\ n") # spend
#
# Provide AP connection
Mac = nic.config('Mac') # Call base Mac address and
mymac=hexmac(Mac) # converted into a hex digit sequence
print("AP Mac: \ T"+mymac+"\ n") # spend
#
nic.ifconfig(("10.0.2.100","255.255.255.0",
"10.0.2.100","10.0.2.100"))
print(nic.ifconfig())
nic.config(authmode=0)
print("Authentication Mode:",nic.config("Authmode"))
nic.config(essid=myssid, password=mypass)
while need nic.active():
print(".",end="")
sleep(1)
print("Nic Active:",nic.active())
Apconf = nic.ifconfig()
print("Sta-IP: \ t \ t",Apconf[0],"\ nsta-netmask: \ t",Apconf[1],"\ nsta-gateway: \ t",Apconf[2] ,sep='')
D.clearall()
D.writer(Apconf[0],0,2)
D.writer(Apconf[1],0,3)
D.writer(Apconf[2],0,4)
sleep(3)
For the changed program you can download powerline_a.py here.
Of course, python must also be installed on the notebook. Version 2.7 is only an option under XP. So the program UDP_Receiver.py runs without problems, here too, two places of a change are required. The best thing to do is invite the patched program udp_receiver_27.py Down, which is then called out of the IDE IDLE. Nothing has to be changed under W10 because the latest version of Python (3.9) provides the same features there, such as Micropython.
So, now you can carry out other series of measurements, with different radiation, for parallel panels or for series circuits of the same.
Have fun researching!