MicroPython Skripte der unterschiedlichen Sensoren

Phyphox-Bibliothek

Zuerst muss man den PhyphoxBLE-Ordner, in der die Phyphox-Bibliothek gespeichert ist, herunterladen: https://github.com/phyphox/phyphox-micropython/tree/main/phyphoxBLE

Diesen Ordner muss man dann auf den ESP laden

Um Sensoren auszulesen und diese in Phyphox anzeigen zu lassen muss man nun die Bibliothek des gewünschten Sensors herunter- und auf den Mikrocontroller daraufladen

Kraftsensor

Kraftsensor-Bibliothek

from machine import Pin, enable_irq, disable_irq, idle

class HX711:
    def __init__(self, dout, pd_sck, gain=128):

        self.pSCK = Pin(pd_sck , mode=Pin.OUT)
        self.pOUT = Pin(dout, mode=Pin.IN, pull=Pin.PULL_DOWN)
        self.pSCK.value(False)

        self.GAIN = 0
        self.OFFSET = 0
        self.SCALE = 1
        
        self.time_constant = 0.1
        self.filtered = 0

        self.set_gain(gain);

    def set_gain(self, gain):
        if gain is 128:
            self.GAIN = 1
        elif gain is 64:
            self.GAIN = 3
        elif gain is 32:
            self.GAIN = 2

        self.read()
        self.filtered = self.read()
        print('Gain & initial value set')
    
    def is_ready(self):
        return self.pOUT() == 0

    def read(self):
        # wait for the device being ready
        while self.pOUT() == 1:
            idle()

        # shift in data, and gain & channel info
        result = 0
        for j in range(24 + self.GAIN):
            state = disable_irq()
            self.pSCK(True)
            self.pSCK(False)
            enable_irq(state)
            result = (result << 1) | self.pOUT()

        # shift back the extra bits
        result >>= self.GAIN

        # check sign
        if result > 0x7fffff:
            resualt -= 0x1000000

        return result

    def read_average(self, times=3):
        sum = 0
        for i in range(times):
            sum += self.read()
        return sum / times

    def read_lowpass(self):
        self.filtered += self.time_constant * (self.read() - self.filtered)
        return self.filtered

    def get_value(self, times=3):
        return self.read_average(times) - self.OFFSET

    def get_units(self, times=3):
        return self.get_value(times) / self.SCALE

    def tare(self, times=15):
        sum = self.read_average(times)
        self.set_offset(sum)

    def set_scale(self, scale):
        self.SCALE = scale

    def set_offset(self, offset):
        self.OFFSET = offset

    def set_time_constant(self, time_constant = None):
        if time_constant is None:
            return self.time_constant
        elif 0 < time_constant < 1.0:
            self.time_constant = time_constant

    def power_down(self):
        self.pSCK.value(False)
        self.pSCK.value(True)

    def power_up(self):
        self.pSCK.value(False)

Code für den Kraftsensor

from phyphoxBLE import PhyphoxBLE, Experiment
from machine import Pin, I2C, ADC
import machine
import time
from hx711 import HX711

dout_pin = 22
sck_pin = 23

hx = HX711(dout_pin, sck_pin)
hx.set_scale(1024)
hx.tare()

lastTimestamp = 0
blinkInterval = 1000
p = PhyphoxBLE()
p.debug = False

def main():
global lastTimestamp
p.start("Kraftsensor")
p._write_callback = receivedData
plot = Experiment()
plot.setTitle("Gewichts-Messung")
plot.setCategory("Micropython Experiments")
plot.setDescription("Der Microcontroller misst das Gewicht der Last")

firstView = Experiment.View()
firstView.setLabel("Gewichts-Messung")
secondView = Experiment.View()
secondView.setLabel("Einstellungen")

abstand = Experiment.Separator()
abstand.setHeight(2.0)

kraftgraph = Experiment.Graph()
kraftgraph.setLabel("Gewichtsmessung")
kraftgraph.setUnitX("s")
kraftgraph.setUnitY("g")
kraftgraph.setLabelX("Zeit")
kraftgraph.setLabelY("Gewicht")
kraftgraph.setXPrecision(1)
kraftgraph.setYPrecision(2)
kraftgraph.setChannel(0,1)

myValue1 = Experiment.Value()
myValue1.setLabel("Gewicht")
myValue1.setPrecision(2)
myValue1.setUnit("g")
myValue1.setColor("FFFFFF")
myValue1.setChannel(1)
myValue1.setXMLAttribute("size=\"2\"")

mySet = Experiment.ExportSet()
mySet.setLabel("Gewichts-Messungen")

myData1 = Experiment.ExportData() 
myData1.setLabel("Zeit")
myData1.setDatachannel(0)

myData2 = Experiment.ExportData() 
myData2.setLabel("Gewicht g")
myData2.setDatachannel(1)

Interval = Experiment.Edit() 
Interval.setLabel("Gewünschter Interval:")
Interval.setUnit("s")
Interval.setSigned(False)
Interval.setDecimal(False)
Interval.setChannel(1)
Interval.setXMLAttribute("min=\"1\"")

myValue2 = Experiment.Value()
myValue2.setLabel("Aktueller Interval:")
myValue2.setPrecision(0)
myValue2.setUnit("s")
myValue2.setColor("FFFFFF")
myValue2.setChannel(2)
myValue2.setXMLAttribute("size=\"2\"")

firstView.addElement(abstand)
firstView.addElement(kraftgraph)
firstView.addElement(abstand)
firstView.addElement(myValue1)
secondView.addElement(abstand)
secondView.addElement(myValue2)
secondView.addElement(Interval)
plot.addView(firstView)
plot.addView(secondView)
mySet.addElement(myData1)
mySet.addElement(myData2)
plot.addExportSet(mySet)
p.addExperiment(plot)

while True:
    if time.ticks_ms()-lastTimestamp > blinkInterval:
        lastTimestamp = time.ticks_ms()
        try:
            weight = hx.get_units()
        except ValueError:
            weight=0
        print(weight)
        machine.idle()
        p.write(weight,blinkInterval/1000)

def receivedData():
global blinkInterval
receivedInterval = p.read()
if receivedInterval > 0 and receivedInterval != blinkInterval:
print("New Interval: ", receivedInterval)
blinkInterval = receivedInterval*1000

if name == "main":
main()

Temperatursensor

Bibliothek vom Temperatursensor

OneWire

# DS18x20 temperature sensor driver for MicroPython.
# MIT license; Copyright (c) 2016 Damien P. George

from micropython import const
from machine import Pin

CMD_CONVERT = const(0x44)
CMD_RDSCRATCH = const(0xbe)
CMD_WRSCRATCH = const(0x4e)
CMD_RDPOWER = const(0xb4)
PULLUP_ON = const(1)
PULLUP_OFF = const(0)

class DS18X20:
    def __init__(self, onewire):
        self.ow = onewire
        self.buf = bytearray(9)
        self.config = bytearray(3)
        self.power = 1 # strong power supply by default
        self.powerpin = None

    def powermode(self, powerpin=None):
        if self.powerpin is not None: # deassert strong pull-up
            self.powerpin(PULLUP_OFF)
        self.ow.writebyte_byte(self.ow.CMD_SKIPROM)
        self.ow.writebyte(CMD_RDPOWER)
        self.power = self.ow.readbit()
        if powerpin is not None:
            assert type(powerpin) is Pin, "Parameter must be a Pin object"
            self.powerpin = powerpin
            self.powerpin.init(mode=Pin.OUT, value=0)
        return self.power

    def scan(self):
        if self.powerpin is not None: # deassert strong pull-up
            self.powerpin(PULLUP_OFF)
        return [rom for rom in self.ow.scan() if rom[0] in (0x10, 0x22, 0x28)]

    def convert_temp(self, rom=None):
        if self.powerpin is not None: # deassert strong pull-up
            self.powerpin(PULLUP_OFF)
        self.ow.reset()
        if rom is None:
            self.ow.writebyte(self.ow.CMD_SKIPROM)
        else:
            self.ow.select_rom(rom)
        self.ow.writebyte(CMD_CONVERT, self.powerpin)

    def read_scratch(self, rom):
        if self.powerpin is not None: # deassert strong pull-up
            self.powerpin(PULLUP_OFF)
        self.ow.reset()
        self.ow.select_rom(rom)
        self.ow.writebyte(CMD_RDSCRATCH)
        self.ow.readinto(self.buf)
        assert self.ow.crc8(self.buf) == 0, 'CRC error'
        return self.buf

    def write_scratch(self, rom, buf):
        if self.powerpin is not None: # deassert strong pull-up
            self.powerpin(PULLUP_OFF)
        self.ow.reset()
        self.ow.select_rom(rom)
        self.ow.writebyte(CMD_WRSCRATCH)
        self.ow.write(buf)

    def read_temp(self, rom):
        try:
            buf = self.read_scratch(rom)
            if rom[0] == 0x10:
                if buf[1]:
                    t = buf[0] >> 1 | 0x80
                    t = -((~t + 1) & 0xff)
                else:
                    t = buf[0] >> 1
                return t - 0.25 + (buf[7] - buf[6]) / buf[7]
            elif rom[0] in (0x22, 0x28):
                t = buf[1] << 8 | buf[0]
                if t & 0x8000: # sign bit set
                    t = -((t ^ 0xffff) + 1)
                return t / 16
            else:
                return None
        except AssertionError:
            return None

    def resolution(self, rom, bits=None):
        if bits is not None and 9 <= bits <= 12:
            self.config[2] = ((bits - 9) << 5) | 0x1f
            self.write_scratch(rom, self.config)
            return bits
        else:
            data = self.read_scratch(rom)
            return ((data[4] >> 5) & 0x03) + 9

    def fahrenheit(self, celsius):
        return celsius * 1.8 + 32 if celsius is not None else None

    def kelvin(self, celsius):
        return celsius + 273.15 if celsius is not None else None

DS18X20-Bibliothek

# DS18x20 temperature sensor driver for MicroPython.
# MIT license; Copyright (c) 2016 Damien P. George

from micropython import const
from machine import Pin

CMD_CONVERT = const(0x44)
CMD_RDSCRATCH = const(0xbe)
CMD_WRSCRATCH = const(0x4e)
CMD_RDPOWER = const(0xb4)
PULLUP_ON = const(1)
PULLUP_OFF = const(0)

class DS18X20:
    def __init__(self, onewire):
        self.ow = onewire
        self.buf = bytearray(9)
        self.config = bytearray(3)
        self.power = 1 # strong power supply by default
        self.powerpin = None

    def powermode(self, powerpin=None):
        if self.powerpin is not None: # deassert strong pull-up
            self.powerpin(PULLUP_OFF)
        self.ow.writebyte_byte(self.ow.CMD_SKIPROM)
        self.ow.writebyte(CMD_RDPOWER)
        self.power = self.ow.readbit()
        if powerpin is not None:
            assert type(powerpin) is Pin, "Parameter must be a Pin object"
            self.powerpin = powerpin
            self.powerpin.init(mode=Pin.OUT, value=0)
        return self.power

    def scan(self):
        if self.powerpin is not None: # deassert strong pull-up
            self.powerpin(PULLUP_OFF)
        return [rom for rom in self.ow.scan() if rom[0] in (0x10, 0x22, 0x28)]

    def convert_temp(self, rom=None):
        if self.powerpin is not None: # deassert strong pull-up
            self.powerpin(PULLUP_OFF)
        self.ow.reset()
        if rom is None:
            self.ow.writebyte(self.ow.CMD_SKIPROM)
        else:
            self.ow.select_rom(rom)
        self.ow.writebyte(CMD_CONVERT, self.powerpin)

    def read_scratch(self, rom):
        if self.powerpin is not None: # deassert strong pull-up
            self.powerpin(PULLUP_OFF)
        self.ow.reset()
        self.ow.select_rom(rom)
        self.ow.writebyte(CMD_RDSCRATCH)
        self.ow.readinto(self.buf)
        assert self.ow.crc8(self.buf) == 0, 'CRC error'
        return self.buf

    def write_scratch(self, rom, buf):
        if self.powerpin is not None: # deassert strong pull-up
            self.powerpin(PULLUP_OFF)
        self.ow.reset()
        self.ow.select_rom(rom)
        self.ow.writebyte(CMD_WRSCRATCH)
        self.ow.write(buf)

    def read_temp(self, rom):
        try:
            buf = self.read_scratch(rom)
            if rom[0] == 0x10:
                if buf[1]:
                    t = buf[0] >> 1 | 0x80
                    t = -((~t + 1) & 0xff)
                else:
                    t = buf[0] >> 1
                return t - 0.25 + (buf[7] - buf[6]) / buf[7]
            elif rom[0] in (0x22, 0x28):
                t = buf[1] << 8 | buf[0]
                if t & 0x8000: # sign bit set
                    t = -((t ^ 0xffff) + 1)
                return t / 16
            else:
                return None
        except AssertionError:
            return None

    def resolution(self, rom, bits=None):
        if bits is not None and 9 <= bits <= 12:
            self.config[2] = ((bits - 9) << 5) | 0x1f
            self.write_scratch(rom, self.config)
            return bits
        else:
            data = self.read_scratch(rom)
            return ((data[4] >> 5) & 0x03) + 9

    def fahrenheit(self, celsius):
        return celsius * 1.8 + 32 if celsius is not None else None

    def kelvin(self, celsius):
        return celsius + 273.15 if celsius is not None else None

Code für den Temperatursensor

from phyphoxBLE import PhyphoxBLE, Experiment
from machine import Pin
from onewire import OneWire
from ds18x20 import DS18X20
import time

pin = Pin(0)
tempSensor = DS18X20(OneWire(pin))
lastTimestamp = 0
blinkInterval = 1000
sensors = tempSensor.scan()
p = PhyphoxBLE()
p.debug = False

def main():
    global lastTimestamp
    p.start("Temperatursensor")
    p._write_callback = receivedData
    plot = Experiment()
    plot.setTitle("Temperaturmessungen")
    plot.setCategory("Micropython Experiments")
    plot.setDescription("Der Microcontroller misst die Temperatur")

    firstView = Experiment.View()
    firstView.setLabel("Temperaturmessung")
    secondView = Experiment.View()
    secondView.setLabel("Einstellungen")
    
    abstand = Experiment.Separator()
    abstand.setHeight(2.0)
    
    #Erste View
    
    firstGraph = Experiment.Graph()
    firstGraph.setLabel("Temperaturmessungen")
    firstGraph.setUnitY("°C")
    firstGraph.setLabelY("Temperatur")
    firstGraph.setXPrecision(1)
    firstGraph.setYPrecision(2)
    firstGraph.setChannel(0,1)
    
    secondGraph = Experiment.Graph()
    secondGraph.setUnitY("°C")
    secondGraph.setLabelY("Temperatur")
    secondGraph.setXPrecision(1)
    secondGraph.setYPrecision(2)
    secondGraph.setChannel(0,2)
    
    thirdGraph = Experiment.Graph()
    thirdGraph.setUnitY("°C")
    thirdGraph.setLabelY("Temperatur")
    thirdGraph.setUnitX("s")
    thirdGraph.setLabelX("Zeit")
    thirdGraph.setXPrecision(1)
    thirdGraph.setYPrecision(2)
    thirdGraph.setChannel(0,3)
    
    mySet = Experiment.ExportSet()
    mySet.setLabel("Temperaturmessungen")

    myData1 = Experiment.ExportData() 
    myData1.setLabel("Zeit")
    myData1.setDatachannel(0)

    myData2 = Experiment.ExportData() 
    myData2.setLabel("Temperatur Celsius")
    myData2.setDatachannel(1)
    
    myData3 = Experiment.ExportData() 
    myData3.setLabel("Temperatur Kelvin")
    myData3.setDatachannel(2)
    
    Interval = Experiment.Edit() 
    Interval.setLabel("Gewünschter Interval:")
    Interval.setUnit("s")
    Interval.setSigned(False)
    Interval.setDecimal(False)
    Interval.setChannel(1)
    Interval.setXMLAttribute("min=\"1\"")
    
    myValue = Experiment.Value()
    myValue.setLabel("Aktueller Interval:")
    myValue.setPrecision(0)
    myValue.setUnit("s")
    myValue.setColor("FFFFFF")
    myValue.setChannel(4)
    myValue.setXMLAttribute("size=\"2\"")
    
    firstView.addElement(abstand)
    firstView.addElement(firstGraph)
    firstView.addElement(secondGraph)
    firstView.addElement(thirdGraph)
    secondView.addElement(abstand)
    secondView.addElement(myValue)
    secondView.addElement(Interval)
    plot.addView(firstView)
    plot.addView(secondView)
    mySet.addElement(myData1)
    mySet.addElement(myData2)
    mySet.addElement(myData3)
    plot.addExportSet(mySet)
    p.addExperiment(plot)
    
    while True:
        
        if time.ticks_ms()-lastTimestamp > blinkInterval:
            lastTimestamp = time.ticks_ms()
            tempSensor.convert_temp()
            digits = 2
            for sensor in sensors:
                temp = tempSensor.read_temp(sensor)
                if temp is not None and type(temp) == float:
                    if sensor == sensors[0]:
                        tempCelsius1 = round(temp, digits)
                    elif sensor == sensors[1]:
                        tempCelsius2 = round(temp, digits)
                    elif sensor == sensors[2]:
                        tempCelsius3 = round(temp, digits)

            p.write(tempCelsius1,tempCelsius2,tempCelsius3,blinkInterval/1000)

def receivedData():
    global blinkInterval
    receivedInterval = p.read()
    if receivedInterval > 0 and receivedInterval != blinkInterval:
        print("New Interval: ", receivedInterval)
        blinkInterval = receivedInterval*1000

if __name__ == "__main__":
    main()

CO2-Sensor

SCD30-Bibliothek

from machine import I2C
import utime
import struct

class SCD30:

    class NotFoundException(Exception):
        pass

    class CRCException(Exception):
        pass

    START_CONT_MEASURE = 0x0010
    STOP_CONT_MEASURE = 0x0104
    SET_MEASURE_INTERVAL = 0x4600
    GET_STATUS_READY = 0x0202
    READ_MEASUREMENT = 0x0300
    SET_ASC = 0x5306
    SET_FRC = 0x5204
    SET_TEMP_OFFSET = 0x5403
    SET_ALT_COMP = 0x5102
    GET_FIRMWARE_VER = 0xd100
    SOFT_RESET = 0xd304

    CLOCK_TIME_US = 10

    # Generated using
    # crc_table = []
    # for crc in range(256):
    #     for crc_bit in range(8):
    #         if crc & 0x80:
    #             crc = (crc << 1) ^ CRC8_POLYNOMIAL;
    #         else:
    #             crc = (crc << 1);
    #         crc = crc%256
    #     crc_table.append(crc)

    CRC_TABLE = [
        0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46,
        67, 114, 33, 16, 135, 182, 229, 212, 250, 203, 152, 169, 62, 15, 92, 109,
        134, 183, 228, 213, 66, 115, 32, 17, 63, 14, 93, 108, 251, 202, 153, 168,
        197, 244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47, 184, 137, 218, 235,
        61, 12, 95, 110, 249, 200, 155, 170, 132, 181, 230, 215, 64, 113, 34, 19,
        126, 79, 28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80,
        187, 138, 217, 232, 127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149,
        248, 201, 154, 171, 60, 13, 94, 111, 65, 112, 35, 18, 133, 180, 231, 214,
        122, 75, 24, 41, 190, 143, 220, 237, 195, 242, 161, 144, 7, 54, 101, 84,
        57, 8, 91, 106, 253, 204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23,
        252, 205, 158, 175, 56, 9, 90, 107, 69, 116, 39, 22, 129, 176, 227, 210,
        191, 142, 221, 236, 123, 74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145,
        71, 118, 37, 20, 131, 178, 225, 208, 254, 207, 156, 173, 58, 11, 88, 105,
        4, 53, 102, 87, 192, 241, 162, 147, 189, 140, 223, 238, 121, 72, 27, 42,
        193, 240, 163, 146, 5, 52, 103, 86, 120, 73, 26, 43, 188, 141, 222, 239,
        130, 179, 224, 209, 70, 119, 36, 21, 59, 10, 89, 104, 255, 206, 157, 172
        ]

    def __init__(self, i2c, addr, pause=1000):
        self.i2c = i2c
        self.pause = pause
        self.addr = addr
        if not addr in i2c.scan():
            raise self.NotFoundException

    def start_continous_measurement(self, ambient_pressure=0):
        bint = struct.pack('>H', ambient_pressure)
        crc = self.__crc(bint[0], bint[1])
        data = bint + bytes([crc])
        self.i2c.writeto_mem(self.addr, self.START_CONT_MEASURE, data, addrsize=16)

    def stop_continous_measurement(self):
        self.__write_command(self.STOP_CONT_MEASURE)

    def soft_reset(self):
        self.__write_command(self.SOFT_RESET)

    def get_firmware_version(self):
        ver = self.__read_bytes(self.GET_FIRMWARE_VER, 3)
        self.__check_crc(ver)
        return struct.unpack('BB', ver)

    def read_measurement(self):
        measurement = self.__read_bytes(self.READ_MEASUREMENT, 18)
        for i in range(0, len(measurement), 3):
            self.__check_crc(measurement[i:i+3])

        value = measurement[0:]
        co2 = struct.unpack('>f', value[0:2] + value[3:5])[0]
        value = measurement[6:]
        temperature = struct.unpack('>f', value[0:2] + value[3:5])[0]
        value = measurement[12:]
        relh = struct.unpack('>f', value[0:2] + value[3:5])[0]
        return (co2, temperature, relh)

    def get_status_ready(self):
        ready = self.__read_bytes(self.GET_STATUS_READY, 3)
        self.__check_crc(ready)
        return struct.unpack('>H', ready)[0]

    def get_measurement_interval(self):
        bint = self.__read_bytes(self.SET_MEASURE_INTERVAL, 3)
        self.__check_crc(bint)
        return struct.unpack('>H', bint)[0]

    def set_measurement_interval(self, interval):
        bint = struct.pack('>H', interval)
        crc = self.__crc(bint[0], bint[1])
        data = bint + bytes([crc])
        self.i2c.writeto_mem(self.addr, self.SET_MEASURE_INTERVAL, data, addrsize=16)

    def get_automatic_recalibration(self):
        bint = self.__read_bytes(self.SET_ASC, 3)
        self.__check_crc(bint)
        return struct.unpack('>H', bint)[0] == 1

    def set_automatic_recalibration(self, enable):
        bint = struct.pack('>H', 1 if enable else 0)
        crc = self.__crc(bint[0], bint[1])
        data = bint + bytes([crc])
        self.i2c.writeto_mem(self.addr, self.SET_FRC, data, addrsize=16)

    def get_forced_recalibration(self):
        bint = self.__read_bytes(self.SET_FRC, 3)
        self.__check_crc(bint)
        return struct.unpack('>H', bint)[0]

    def set_forced_recalibration(self, co2ppm):
        bint = struct.pack('>H', co2ppm)
        crc = self.__crc(bint[0], bint[1])
        data = bint + bytes([crc])
        self.i2c.writeto_mem(self.addr, self.SET_FRC, data, addrsize=16)

    def get_temperature_offset(self):
        bint = self.__read_bytes(self.SET_TEMP_OFFSET, 3)
        self.__check_crc(bint)
        return struct.unpack('>H', bint)[0] / 100.0

    def set_temperature_offset(self, offset):
        bint = struct.pack('>H', int(offset * 100))
        crc = self.__crc(bint[0], bint[1])
        data = bint + bytes([crc])
        self.i2c.writeto_mem(self.addr, self.SET_TEMP_OFFSET, data, addrsize=16)

    def get_altitude_comp(self):
        bint = self.__read_bytes(self.SET_ALT_COMP, 3)
        self.__check_crc(bint)
        return struct.unpack('>H', bint)[0]

    def set_altitude_comp(self, altitude):
        bint = struct.pack('>H', altitude)
        crc = self.__crc(bint[0], bint[1])
        data = bint + bytes([crc])
        self.i2c.writeto_mem(self.addr, self.SET_ALT_COMP, data, addrsize=16)

    def __write_command(self, cmd):
        bcmd = struct.pack('>H', cmd)
        self.i2c.writeto(self.addr, bcmd)

    def __read_bytes(self, cmd, count):
        self.__write_command(cmd)
        utime.sleep_us(self.pause)
        return self.i2c.readfrom(self.addr, count)

    def __check_crc(self, arr):
        assert (len(arr) == 3)
        if self.__crc(arr[0], arr[1]) != arr[2]:
            raise self.CRCException

    def __crc(self, msb, lsb):
        crc = 0xff
        crc ^= msb
        crc = self.CRC_TABLE[crc]
        if lsb is not None:
            crc ^= lsb
            crc = self.CRC_TABLE[crc]
        return crc

SCD30-Code

from phyphoxBLE import PhyphoxBLE, Experiment
from machine import Pin, SoftI2C
from scd30 import SCD30
from machine import Pin, I2C
from time import sleep_ms

i2c = SoftI2C(sda=Pin(21), scl=Pin(22))
readyPin = Pin(23, Pin.IN, Pin.PULL_UP)
devices = i2c.scan()

for device in devices:
    if device == 0x61:
        scd30_address = device
        break

scd30_sensor = SCD30(i2c, scd30_address)
scd30_sensor.start_continous_measurement()

blinkInterval = 300000
lastTimestamp = 0
p = PhyphoxBLE()
p.debug = False

def main():
    global lastTimestamp
    p.start("CO2-Sensor")
    p._write_callback = receivedData
    plot = Experiment()
    plot.setTitle("CO2-Messung")
    plot.setCategory("Micropython Experiments")
    plot.setDescription("Der Microcontroller misst den CO2-Gehalt in der Luft")

    firstView = Experiment.View()
    firstView.setLabel("CO2-Messung")
    secondView = Experiment.View()
    secondView.setLabel("Einstellungen")
    
    abstand = Experiment.Separator()
    abstand.setHeight(2.0)
    
    #Erste View
    
    firstGraph = Experiment.Graph()
    firstGraph.setLabel("CO2-Messung")
    firstGraph.setUnitY("ppm")
    firstGraph.setLabelY("Konzentration")
    firstGraph.setXPrecision(1)
    firstGraph.setYPrecision(2)
    firstGraph.setChannel(0,1)
    
    secondGraph = Experiment.Graph()
    secondGraph.setUnitY("°C")
    secondGraph.setLabelY("Temperatur")
    secondGraph.setXPrecision(1)
    secondGraph.setYPrecision(2)
    secondGraph.setChannel(0,2)
    
    thirdGraph = Experiment.Graph()
    thirdGraph.setUnitY("%")
    thirdGraph.setLabelY("Luftfeuchtigkeit")
    thirdGraph.setUnitX("s")
    thirdGraph.setLabelX("Zeit")
    thirdGraph.setXPrecision(1)
    thirdGraph.setYPrecision(2)
    thirdGraph.setChannel(0,3)
    
    mySet = Experiment.ExportSet()
    mySet.setLabel("CO2-Messungen")

    myData1 = Experiment.ExportData() 
    myData1.setLabel("Zeit")
    myData1.setDatachannel(0)

    myData2 = Experiment.ExportData() 
    myData2.setLabel("CO2-Konzentration")
    myData2.setDatachannel(1)
    
    myData3 = Experiment.ExportData() 
    myData3.setLabel("Temperatur")
    myData3.setDatachannel(2)
    
    myData4 = Experiment.ExportData() 
    myData4.setLabel("Luftfeuchtigkeit")
    myData4.setDatachannel(3)
    
    Interval = Experiment.Edit() 
    Interval.setLabel("Gewünschter Interval:")
    Interval.setUnit("s")
    Interval.setSigned(False)
    Interval.setDecimal(False)
    Interval.setChannel(1)
    Interval.setXMLAttribute("min=\"1\"")
    
    myValue = Experiment.Value()
    myValue.setLabel("Aktueller Interval:")
    myValue.setPrecision(0)
    myValue.setUnit("s")
    myValue.setColor("FFFFFF")
    myValue.setChannel(4)
    myValue.setXMLAttribute("size=\"2\"")
    
    firstView.addElement(abstand)
    firstView.addElement(firstGraph)
    firstView.addElement(secondGraph)
    firstView.addElement(thirdGraph)
    secondView.addElement(abstand)
    secondView.addElement(myValue)
    secondView.addElement(Interval)
    plot.addView(firstView)
    plot.addView(secondView)
    mySet.addElement(myData1)
    mySet.addElement(myData2)
    mySet.addElement(myData3)
    mySet.addElement(myData4)
    plot.addExportSet(mySet)
    p.addExperiment(plot)
    
    while True:
        while readyPin.value() != 1:
            sleep_ms(200)
        # Lese die Sensordaten
        co2, temperature, humidity = scd30_sensor.read_measurement()

        # Runde die Werte auf zwei Nachkommastellen
        co2 = round(co2, 2)
        temperature = round(temperature, 2)
        humidity = round(humidity, 2)
        
        
        # Gib die Werte aus
        print("******************************")
        print("CO2: {} ppm".format(co2))
        print("Temperatur: {} °C".format(temperature))
        print("Luftfeuchtigkeit: {} %".format(humidity))
        
        p.write(co2,temperature,humidity,blinkInterval/1000)
            
def receivedData():
    global blinkInterval
    receivedInterval = p.read()
    if receivedInterval > 0 and receivedInterval != blinkInterval:
        print("New Interval: ", receivedInterval)
        blinkInterval = receivedInterval*1000
        
if __name__ == "__main__":
    main()

Tag 4 – Can und Paul

Heute morgen lief alles wie geplant. Nachdem wir in unserer Freizeit weitergearbeitet haben, funktionierte unser Code wie erwünscht. Unser Auto konnte geradeaus fahren, bis der Ultraschallsensor eine Distanz von < 10 cm gemessen hat, dann hat es angehalten. Wir haben am Code gearbeitet, und ihn zu verändert, dass das Auto ein Rad dreht wenn etwas vor ihm ist (sich also um die eigene Achse dreht) und dann fährt es weiter. Das ganze geht mit einem Knopf an und aus. Zusätzlich haben wir einen OLED-Display eingebaut, welcher die Distanzen anzeigt und eine LED welcher leuchtet wenn das Auto geradeaus fährt. Zuletzt haben wir den Code noch im boot.py gespeichert, damit es ohne Verbindung zum Laptop läuft, denn wir haben jezt einen Akku, welcher für den Strom sorgt.

Tag 3: Improvisierung

  • Heute haben wir uns mit dem Freenove Car Kit beschäftigt und versucht, es in Bewegung zu bringen.
  • Wir haben versucht, ein Infrarotsignal von einem Sender an einen Empfänger zu senden, um das Auto zu steuern.
  • Leider haben wir Schwierigkeiten bei der Signalübertragung und der Steuerung des Autos erfahren.
  • Daher haben wir uns entschlossen, eine Alternative zu finden und haben uns für den Bau einer Flipbox entschieden.
  • Die Flipbox besteht aus zwei Motoren, die über einen ESP32 und Joysticks gesteuert werden können.
  • Wir glauben, dass die Flipbox ein aufregendes und herausforderndes Projekt sein wird, das uns die Möglichkeit gibt, unsere Fähigkeiten in Elektronik und Programmierung zu verbessern.

Tag 2

Heute Morgen haben wir zuerst Achsen für unser Auto hergestellt. Sie sollten die Step-Motoren mit den Rädern verbinden. Das Arbeiten mit Fusion 360 war uns fremd und das 3D-Drucken hat lange gedauert, deshalb hatten wir erst am Nachmittag die fertigen Achsen. Zusätzlich ist die erste Version unseres Endcodes fertig. Alles klappt noch nicht wie erwüncht, wir sind aber ein Schritt näher am Endprodukt. Unser Auto haben wir am späten Nachmittag zusammen bauen können, als wir mit dem Druck fertig waren. Wir haben als Vorderrad eine Kugel, damit wir nur zwei Motoren koordinieren müssen. So wird die Rotation des Autos einfacher.

Bewegungsmelder mit ESP32

In unserem Projekt werden wir einen Bewegungsmelder mit einem ESP32 bauen. Der Infrarotsensor, der mit dem ESP32 verbunden ist, erkennt Bewegungen und sendet eine Benachrichtigung an Ihr Telefon.

Tag 1:
Wir haben mit dem Bewegungsmelder experimentiert und sind dabei auf einige Schwierigkeiten gestoßen. Er funktionierte nicht richtig, er erkannte Bewegung, wenn es keine Bewegung gab, und war sehr inkonsistent, wenn es tatsächlich Bewegung gab. Mit Hilfe eines Lehrers begannen wir zu verstehen, wie er funktioniert, und machten erste Fortschritte. In der Zwischenzeit suchten wir nach Programmen, die das Telefon benachrichtigen konnten. Wir stellten fest, dass keines der Programme kostenlos war, und die einzige Möglichkeit bestand darin, kostenlose Testversionen zu verwenden. Also erstellten wir ein Konto und starteten eine kostenlose Testversion auf zwei Websites: Twilio und Nexmo.

Am Nachmittag versuchten wir weiter, den Bewegungsmelder richtig zum Laufen zu bringen, aber er funktionierte nicht so, wie wir es wollten. Dann versuchten wir es mit einem anderen Sensor, der die Entfernung misst (HC-sr501), und dachten, wir könnten ihn so programmieren, dass er bei einem Abstandsunterschied weiß, dass etwas vor ihm vorbeigegangen ist, und er erkennt eine Bewegung. Dieser Sensor funktionierte besser, und wir könnten uns dafür entscheiden, diesen eSensor zu verwenden.

Unser Ziel für morgen ist es, dass es funktioniert, zuerst mit einer LED, was einfacher ist, und dann mit dem Programm, das eine Benachrichtigung an Ihr Telefon sendet.

Tag 2:

Wir haben den neuen Sensor sehr schnell zum Laufen gebracht, also haben wir versucht, die Programme, die eine Nachricht an das Telefon senden, in den Code einzubauen, und sind schnell auf einige Probleme gestoßen. Wir mussten eine Menge Dinge installieren, damit das funktioniert, die meisten direkt auf dem ESP32, und nach ein paar Stunden des Ausprobierens und des Fragens nach Hilfe von verschiedenen Leuten, wurde uns klar, dass es nicht funktionieren würde. Der ESP32 war nicht kompatibel oder für unser Projekt gemacht, die direkte Kommunikation zwischen ESP32 und einem Mobiltelefon wäre unmöglich. Nach anderthalb Tagen war uns klar, dass wir unser Projekt nicht beenden konnten und uns etwas Neues einfallen lassen mussten. Wir kehrten zum Sensor zurück und überlegten, so viel wie möglich auf der Hauptplatine zu machen. Wir wollten Lichter und Buzzer hinzufügen, damit er auch als eine Art Sicherheitseinrichtung funktioniert. Wenn jemand durch sie hindurchgeht, würde sie Licht und Geräusche machen und so einen Alarm auslösen.


PhyPhox

PhyPhox ist eine leistungsstarke App für Android und iOS, die es Ihnen ermöglicht, physikalische Experimente und Messungen auf Ihrem Smartphone oder Tablet durchzuführen. Die App wurde von der Universität Siegen entwickelt und ist für den Einsatz im Unterricht, Labor oder für Forschungszwecke geeignet. PhyPhox ist eine benutzerfreundliche Anwendung, die für alle Altersgruppen geeignet ist und Ihnen eine Fülle von Funktionen und Experimenten zur Verfügung stellt.

Mit PhyPhox können Sie eine Vielzahl von Experimenten durchführen, die das volle Potenzial Ihres Smartphones oder Tablets nutzen. Zum Beispiel können Sie mit der App den Beschleunigungssensor verwenden, um die Schwerkraft zu messen oder den Gyrosensor, um Drehbewegungen zu erfassen. Darüber hinaus können Sie auch den Magnetometer verwenden, um das Erdmagnetfeld zu messen, oder den Lichtsensor, um die Helligkeit zu messen.

PhyPhox ist auch eine großartige Ressource für den Unterricht, da die App spezielle Experimente für den Einsatz im Klassenzimmer bietet. Diese Experimente sind speziell für Schülerinnen und Schüler entwickelt worden, um ihnen dabei zu helfen, physikalische Konzepte zu verstehen und ihre Fähigkeiten im Umgang mit Experimenten und Messungen zu verbessern.

Mit PhyPhox können Sie Ihre Experimente aufzeichnen und die Ergebnisse in Echtzeit anzeigen lassen. Sie können die Ergebnisse auch in verschiedenen Formaten exportieren, um sie später zu analysieren oder zu präsentieren.

Insgesamt ist PhyPhox eine äußerst nützliche App für alle, die an physikalischen Experimenten und Messungen interessiert sind. Wenn Sie mehr über PhyPhox erfahren möchten oder Unterstützung bei der Verwendung der App benötigen, stehe ich gerne zur Verfügung.

PhyPhox BLE: Verwenden Sie phyphox mit Ihrem ESP32

PhyPhox ist eine Open-Source-App, die an der RWTH Aachen University entwickelt wurde und auf Android und iOS verfügbar ist. Ziel der App ist es, die Sensoren Ihres Smartphones für physikalische Experimente und Messungen zugänglich zu machen. Doch wussten Sie, dass Sie PhyPhox auch mit Ihrem ESP32-Mikrocontroller erweitern können?

Mit der PhyPhox BLE-Bibliothek können Sie den ESP32 nutzen, um Sensordaten an Ihr Smartphone zu senden oder umgekehrt, um Daten von Ihrem Smartphone zu Ihrem Mikrocontroller zu übertragen. Die Bibliothek erstellt eine Experiment-Konfiguration im flexiblen Dateiformat von PhyPhox, die Sie direkt auf Ihr Smartphone übertragen können.

Sie können diese Bibliothek verwenden, um eine Vielzahl von Experimenten durchzuführen, die das volle Potenzial Ihres ESP32 nutzen. Beispielsweise können Sie mit Hilfe der PhyPhox BLE-Bibliothek Sensordaten von Ihrem ESP32 an Ihr Smartphone senden, um sie in Echtzeit zu plotten und zu analysieren. Oder Sie können Sensordaten von Ihrem Smartphone an Ihren ESP32 senden, um sie in Ihrem eigenen MicroPython-Projekt zu verarbeiten.

Die PhyPhox BLE-Bibliothek ist eine großartige Möglichkeit, die Leistungsfähigkeit Ihres ESP32 voll auszuschöpfen und ihn in die Welt der physikalischen Experimente und Messungen einzuführen. Wenn Sie mehr über die Verwendung von PhyPhox mit Ihrem ESP32 erfahren möchten oder Unterstützung bei der Verwendung der PhyPhox BLE-Bibliothek benötigen, stehe ich Ihnen gerne zur Verfügung.

Hier folgen in Kürze ein paar Beispiel aus dem Unterricht.

Jetzt mit Python-Code

Sie können mit WordPress auch Python-Code direkt auf der Seite einfügen. Dazu müssen Sie einfach auf das +  klicken um einen Beitrag hinzuzufügen und dann als Beitragstyp code block  auswählen.

import python