"""Pulse counting (ULP co-processor).
The :class:`counter` class below is **verbatim** from the device
firmware (``firmware_core.py`` of Logger Pro v9).
Analog measurement note:
There is no separate analog-sensor class in the firmware. Raw ADC
conversions are done by :meth:`findylab.core.fw.adcMeasure` and the
4-20 mA scaling happens inline in the user-editable ``measure()``
hook in ``last.py``::
ina1 = round(self.adcMeasure(b'\x90') / 100, 2) # mA
qty = (ina1 - sensor_min) * ((qty_max - qty_min) /
(sensor_max - sensor_min))
with the calibration values read from parameters 553-556 (AIN1) or
578-581 (AIN2) - see :doc:`/datatypes/system-ids`.
"""
import time
import utime
import struct
import machine
from machine import mem32
[docs]
class counter(object):
"""ULP pulse counting on the two digital inputs (IO4/IO14).
Verbatim class from ``firmware_core.py``. The ESP32 ULP
co-processor samples the inputs every few milliseconds and counts
debounced edges - including during deep sleep. Never instantiated;
the methods take no ``self``::
counter.getSamplings()
Note:
Requires ``ulp_main.bin`` in the device filesystem - without it
:meth:`initCounter` raises ``OSError`` (``ENOENT``).
"""
[docs]
def valFromMem(val):
"""Reads one counter value from ULP memory.
Edge counters count both edges, so the raw value is halved.
Args:
val (int): ULP memory address.
Returns:
int: Pulse count (raw edge count // 2).
"""
from machine import mem32
return (mem32[val] & 0xFFFF)//2
[docs]
def printAllSamplings():
"""Dumps the ULP sample memory to the console (debug aid)."""
from machine import mem32
aa = 0x500002a0
#the addition of 8 is to keep a visible guard area
io4 = []
io14 = []
even = True
while aa < ( 0x500002a0 + ( (0x168 - 0x10)*4)) :
print(str(hex(aa)) + " = "+ hex(mem32[aa]))
aa +=4
[docs]
def getSamplings():
"""Collects the pulse deltas since the previous wakeup.
Verifies the ULP is alive (restarts it and clears the tracking
parameters when frozen), reads both edge counters, computes the
deltas with 15-bit overflow handling, accumulates them into
parameters 437/439 and appends the deltas to ring-buffers
540/541.
"""
ulp_edge_count = 0x50000228
ulp_edge_count1 = 0x5000022c
ulp_alive_counter = 0x5000023c
ulp_save_counter=0x50000244
ulp_memory_pointer=0x50000248
ulp_max_memory_pointer = 0x5000024c
alive = hex(mem32[ulp_alive_counter])
time.sleep(0.2)
#print("Alive Counter")
#print(hex(mem32[ulp_alive_counter]))
# Reset if there's no activity from the ULP
ulpReset = False
if alive == hex(mem32[ulp_alive_counter]):
print("ULP is not working")
counter.initCounter()
db.write('532','0')
db.write('533','0')
time.sleep(1)
ulpReset = True
#Calculate the difference of the edge counter and handle overflow
currentEdge4 = counter.valFromMem(ulp_edge_count)
currentEdge14 = counter.valFromMem(ulp_edge_count1)
#print("Current Edge 4 = ",currentEdge4)
#print("Current Edge 14 = ",currentEdge14)
previousEdge4 = int(db.read('532'))
previousEdge14 = int(db.read('533'))
counter4 = int(db.read('437'))
counter14 = int(db.read('439'))
#print("Previous Edge 4 = ",previousEdge4)
#print("Previous Edge 14 = ",previousEdge14)
if ulpReset:
print("ULP Reset exit!")
currentEdge14 = previousEdge14
currentEdge4 = previousEdge4
return
if currentEdge4 < previousEdge4:
print("!!!Overflow 4 !!!")
delta4 = (32767-previousEdge4) + currentEdge4
#currentEdge4 = (32767-previousEdge4) + previousEdge4 + currentEdge4
#print("New Current ", currentEdge4)
else:
delta4 = currentEdge4-previousEdge4
if currentEdge14 < previousEdge14:
print("!!!Overflow 14 !!!")
delta14 = (32767-previousEdge14) + currentEdge14
#currentEdge4 = (32767-previousEdge4) + previousEdge4 + currentEdge4
#print("New Current ", currentEdge4)
else:
delta14 = currentEdge14-previousEdge14
#print("Delta4 = ",delta4)
#print("Delta14 = ",delta14)
old4 = counter4
old14 = counter14
counter4 = counter4+delta4
newEdgge4 = currentEdge4 + delta4
db.write('437',counter4)
db.write('532',currentEdge4)
counter14 = counter14+delta14
newEdgge14 = currentEdge14 + delta14
db.write('439',counter14)
db.write('533',currentEdge14)
moment4 = counter4-old4
moment14 = counter14 - old14
#buffer.put('540',struct.pack("B", moment4) + b'\xff\xff')
#
#buffer.put('541',struct.pack("B", moment14) + b'\xff\xff')
buffer.put('540',moment4.to_bytes(2, 'big') )
buffer.put('541',moment14.to_bytes(2, 'big'))
return
[docs]
def initCounter():
"""Loads and starts the ULP counting program.
Loads ``ulp_main.bin``, configures the input pins, debounce,
wakeup pulse count and the save period (from parameter 421),
starts the co-processor and opens fresh ring-buffer slots.
Raises:
OSError: When ``ulp_main.bin`` is missing (``ENOENT``).
"""
import esp32
from machine import mem32
from machine import Pin
ulp_debounce_counter = 0x5000021c
ulp_debounce_counter1 = 0x50000220
ulp_debounce_max_count = 0x50000224
ulp_edge_count = 0x50000228
ulp_edge_count1 = 0x5000022c
ulp_io_number = 0x50000234
ulp_io_number2 = 0x50000238
ulp_edge_count_to_wake_up = 0x50000230
ulp_alive_counter = 0x5000023c
ulp_save_period=0x50000240
ulp_save_counter=0x50000244
ulp_memory_pointer=0x50000248
ulp_max_memory_pointer = 0x5000024c
u = esp32.ULP()
f = open('ulp_main.bin','rb')
binary = f.read()
# 5000 = 5ms. Pulse = wakeUp_period*debounce*2
u.set_wakeup_period(0, 13888)
u.load_binary(0,binary)
#IO 4
mem32[ulp_io_number] = 10
#IO 14
mem32[ulp_io_number2] = 16
#How many edges at the same level have been caught
mem32[ulp_debounce_counter] = 5
mem32[ulp_debounce_counter1] = 5
#How many times the same value must occur to accept a pulse
mem32[ulp_debounce_max_count] = 2
#Pulse count - edge Counter/2
mem32[ulp_edge_count] = 0
mem32[ulp_edge_count1] = 0
#After how many pulses it should wake us up
mem32[ulp_edge_count_to_wake_up] = 10
#how many times it has woken up, whether the ULP is working (5ms)
mem32[ulp_alive_counter] = 0
#Every how many wakeups to save a value. 12000 -> a minute. Max -> 65000
#wakeup * Save
#mem32[ulp_save_period] = 60000
period = db.read('421')
#square(900/5000)
#square(desired time/5000)
#write frequency = pow(savePeriod*ulpTime (5000))
mem32[ulp_save_period] = 72*int(period)#6000
#Don't touch
mem32[ulp_memory_pointer] = 0x10
mem32[ulp_max_memory_pointer] = 0x168
u.run(0)
timestamp = device.getTimestamp()
#db.write('443',timestamp)
#timestamp = device.setTimestamp()
#db.write('443',timestamp)
buffer.create('540')
buffer.create('541')