class ANGLE(): # 1 def __init__(self, port=PORTB): global class_map from machine import ADC if class_map['adc'] != None: class_map['adc'].deinit() self.adc = ADC(PORTB[1]) self.adc.atten(ADC.ATTN_11DB) class_map['adc'] = self.adc def deinit(self): self.adc.deinit() def readraw(self): return 4095 - self.adc.readraw() def read(self): data = 0 max = 0 min = 4096 for i in range(0, 10): newdata = 4095 - self.adc.readraw() data += newdata if newdata > max: max = newdata if newdata < min: min = newdata data -= (max + min) data >>= 3 return round(1024 * data / 4095, 2)
class Battery: """ TODO: Have to calibrate the results voltage using Vref on efuse. But the necessary functions seem not to be implemented to MicroPython yet. * esp_adc_cal_characterize() * esp_adc_cal_raw_to_voltage() This module calculate current battery voltage roughly for now. """ def __init__(self, battery_pin, battery_resistance_num, width, atten): self._battery_adc = ADC(Pin(battery_pin)) self._battery_adc.width(width) self._battery_adc.atten(atten) self._battery_resistance_num = battery_resistance_num def get_voltage(self, sampling_count=32, round_count=3): raw_value = sum( [self._battery_adc.read() for _ in range(sampling_count)]) / sampling_count voltage = raw_value * self._battery_resistance_num / 1000 return round(voltage, round_count) def deinit(self): """ Deinitialize the battery pin ADC """ self._battery_adc.deinit()
class Light: def __init__(self, port): from machine import ADC, Pin self.adc = ADC(port[1]) self.adc.atten(ADC.ATTN_11DB) self.d_pin = Pin(port[0], Pin.IN, Pin.PULL_UP) @property def analogValue(self): data = 0 max = 0 min = 4096 for i in range(0, 10): newdata = 4095 - self.adc.readraw() data += newdata if newdata > max: max = newdata if newdata < min: min = newdata data -= (max + min) data >>= 3 return round(1024 * data / 4095, 2) @property def digitalValue(self): return self.d_pin.value() def deinit(self): self.adc.deinit()
class Angle: def __init__(self, port): from machine import ADC self.adc = ADC(port[1]) self.adc.atten(ADC.ATTN_11DB) def deinit(self): self.adc.deinit() def readraw(self): return 4095 - self.adc.readraw() def read(self): data = 0 max = 0 min = 4096 for i in range(0, 10): newdata = 4095 - self.adc.readraw() data += newdata if newdata > max: max = newdata if newdata < min: min = newdata data -= (max + min) data >>= 3 return round(1024 * data / 4095, 2)
class ANGLE(): # 1 def __init__(self, port=PORTB): from machine import ADC self.adc = ADC(36) self.adc.atten(ADC.ATTN_11DB) def deinit(self): self.adc.deinit() def readraw(self): return 4095 - self.adc.readraw() def read(self): data = 0 max = 0 min = 4096 for i in range(0, 10): newdata = 4095 - self.adc.readraw() data += newdata if newdata > max: max = newdata if newdata < min: min = newdata data -= (max + min) data >>= 3 return 100 * data / 4095
def adc(): adc = ADC() adc.init(bits=12) #adc_c = adc.channel(pin='P13',attn=ADC.ATTN_11DB) #ADC pin input range is 0-3.3V with 11DB. adc_c = adc.channel(pin='P13') #ADC pin input range is 0-1.1V. for cycles in range(10): # stop after 10 cycles #pycom.rgbled(0x007f00) # green Vx= adc_c.value() #pycom.rgbled(0x7f7f00) # yellow print("ADC value:", Vx) time.sleep(1) adc.deinit() return Vx
class MQ131: #Sensor datasheet has a graphical representation of ppm of gas by Rs/R0. By obtaining this ratio and using the graphical funcion one can obtain the gas density in ppm #Rs is the resistance of the sensor that changes depending on the concentration of gas #R0 is the resistance of the sensor at a know concentration without the presence of gases (fresh air) #Rs/R0 of fresh air is 1 so R0=Rs/1 #2 points of the gas function are selected (1.2 at 10ppm) and (8 at 1000ppm) #another point is used to find the intersect (6 at 500ppm) READ_SAMPLE_INTERVAL = const(500) READ_SAMPLE_TIMES = const(10) def __init__(self, pin, R0): self.pin = pin self.R0 = R0 self.adc = ADC(bits=12) self.adc.vref_to_pin('P22') self.apin = self.adc.channel(pin=self.pin, attn=ADC.ATTN_11DB) def deinit(self): self.apin.deinit() self.adc.deinit() def MQRead(self): v=float(0) for i in range(READ_SAMPLE_TIMES): v += self.apin() sleep(READ_SAMPLE_INTERVAL/1000) return ((v/READ_SAMPLE_TIMES)*3.3/4096) #3.3v - ATTN_11DB & 4096 - 12bits def MQCalibrate_R0(self, volts): #Rs = (Vc * RL)/VRL - RL if (volts==0): return 0 RS_air = ((5.0*10.0)/volts)-10.0 R0_air = RS_air/1 #from graph, needs to be replaced with real data return R0_air def MQGet_PPB(self, volts): if (volts==0): return 0 Rs = ((5.0*10.0)/volts)-10.0 m=AdvMath.log10(1.2/10)/AdvMath.log10(8/1000) b=AdvMath.log10(6)-(m*AdvMath.log10(500)) if (Rs==0): return 0 return pow(10,(((AdvMath.log10(Rs/self.R0))-b)/m))
class linear_encoder: def __init__(self, adc_pin, a, b): from machine import ADC, Pin self.a = a self.b = b self.adc_in = ADC(Pin(adc_pin)) self.adc_in.atten(ADC.ATTN_11DB) self.adc_in.width(ADC.WIDTH_12BIT) def read(self): x = self.adc_in.read() y = self.a * x + self.b return y def deinit(self): self.adc_in.deinit()
class Battery(object): """ Expansion board has battery on GP3 The ADC measures between 0-1.4V It is 12bit (0-4095) It is measuring off a 56k/(56k+115k) voltage divider - 0.32 """ MINIMUM = 3180 # 3.64V measured CHARGED = 3600 # Using 4.15V RANGE = (CHARGED - MINIMUM) def __init__(self): self.adc = ADC() self.battery_raw = self.adc.channel(pin='GP3') def __del__(self): self.battery_raw.deinit() self.adc.deinit() def safe(self): """ Is battery at operating voltage? :return: True/False """ return self.battery_raw() >= Battery.MINIMUM def value(self): """ Battery percentage :return: 0-100 """ val = (self.battery_raw() - Battery.MINIMUM) * 100 val = val // Battery.RANGE if val > 100: val = 100 if val < 0: val = 0 return val
class SEN0219: #Sensor datasheet has a graphical representation of ppm of gas by V in a linear function. By using the graphical funcion one can obtain the gas density in ppm #2 points of the gas function are used to find the slope of the linear function (2V at 5000ppm) and (0.4 at 0ppm) #To Calibrate the Sensor by Hardware, one should place it in a CO2 free enviroment and then wire to ground both pin 8 and 20 of the Sensor for 7 seconds #To Calibrate the Sensor by Software, one should place it in a enviroment close to average CO2 (400ppm), measure the voltage output, and use that value as R0 READ_SAMPLE_INTERVAL = const(500) READ_SAMPLE_TIMES = const(10) def __init__(self, pin, offset): self.pin = pin self.offset = offset self.adc = ADC(bits=12) self.apin = self.adc.channel(pin=self.pin, attn=ADC.ATTN_11DB) def deinit(self): self.apin.deinit() self.adc.deinit() def SENRead(self): v=float(0) for i in range(READ_SAMPLE_TIMES): v += self.apin() sleep(READ_SAMPLE_INTERVAL/1000) return ((v/READ_SAMPLE_TIMES)*3.3/4096) #3.3v - ATTN_11DB & 4096 - 12bits def SENCalibrate_offset(self, volts): # 0,528V -> 400 ppm if (volts<=0.528): return 0 offset = (((volts-0.4)*5000)/1.6) - 400 return offset def SENGet_PPM(self, volts): if (volts<=0.4): return False ppm=(((volts-0.4)*5000)/1.6)-self.offset #0.4 = Zero & (5000-0)/(2-0.4) = Linear Function return ppm
class gameESP(): max_vol = 6 duty = {0: 0, 1: 0.05, 2: 0.1, 3: 0.5, 4: 1, 5: 2, 6: 70} tones = { 'c4': 262, 'd4': 294, 'e4': 330, 'f4': 349, 'f#4': 370, 'g4': 392, 'g#4': 415, 'a4': 440, "a#4": 466, 'b4': 494, 'c5': 523, 'c#5': 554, 'd5': 587, 'd#5': 622, 'e5': 659, 'f5': 698, 'f#5': 740, 'g5': 784, 'g#5': 831, 'a5': 880, 'b5': 988, 'c6': 1047, 'c#6': 1109, 'd6': 1175, ' ': 0 } def __init__(self): # True = SPI display, False = I2C display self.ESP32 = True self.paddle2 = False self.useSPI = True self.timer = 0 self.vol = int(self.max_vol / 2) + 1 seed(ticks_us()) self.btnU = 1 << 1 self.btnL = 1 << 2 self.btnR = 1 << 3 self.btnD = 1 << 4 self.btnA = 1 << 5 self.btnB = 1 << 6 self.btnUval = 0 self.btnDval = 0 self.btnLval = 0 self.btnRval = 0 self.btnAval = 0 self.btnBval = 0 self.frameRate = 30 self.screenW = 128 self.screenH = 64 self.Btns = 0 self.lastBtns = 0 self.PinBuzzer = Pin(26, Pin.OUT) # configure oled display SPI SSD1306 self.spi = SPI(2, baudrate=14500000, sck=Pin(18), mosi=Pin(23), miso=Pin(19)) # display = Display(spi, rst=Pin(4), dc=Pin(21), cs=Pin(5), ) #DC, RES, CS self.display = SSD1306_SPI(128, 64, self.spi, Pin(21), Pin(4), Pin(5)) self.PinBtnA = Pin(32, Pin.IN, Pin.PULL_UP) self.PinBtnB = Pin(33, Pin.IN, Pin.PULL_UP) self.adcX = ADC(34) self.adcY = ADC(35) self.adc = ADC(39) self.adcX.atten(ADC.ATTN_11DB) self.adcY.atten(ADC.ATTN_11DB) self.adc.atten(ADC.ATTN_11DB) def deinit(self): self.adc.deinit() self.adcX.deinit() self.adcY.deinit() if self.useSPI: self.spi.deinit() def getPaddle(self): # ESP32 - 142 to 3155 return max(min(int(self.adc.read() / 2.935) - 48, 1023), 0) def pressed(self, btn): return (self.Btns & btn) def justPressed(self, btn): return (self.Btns & btn) and not (self.lastBtns & btn) def justReleased(self, btn): return (self.lastBtns & btn) and not (self.Btns & btn) def getBtn(self): self.btnAval = not self.PinBtnA.value() self.btnBval = not self.PinBtnB.value() val = self.adcX.read() self.btnLval = 1 if val > 2500 else 0 self.btnRval = 1 if 1500 < val < 2000 else 0 val = self.adcY.read() self.btnUval = 1 if val > 2500 else 0 self.btnDval = 1 if 1500 < val < 2000 else 0 self.lastBtns = self.Btns self.Btns = 0 self.Btns = self.Btns | self.btnUval << 1 | self.btnLval << 2 | self.btnRval << 3 | self.btnDval << 4 | self.btnAval << 5 | self.btnBval << 6 return self.Btns print(self.Btns) def setVol(self): if self.pressed(self.btnB): if self.justPressed(self.btnU): self.vol = min(self.vol + 1, self.max_vol) self.playTone('c4', 100) return True elif self.justPressed(self.btnD): self.vol = max(self.vol - 1, 0) self.playTone('d4', 100) return True return False def playTone(self, tone, tone_duration, rest_duration=0): beeper = PWM(self.PinBuzzer, freq=self.tones[tone], duty=self.duty[self.vol]) sleep_ms(tone_duration) beeper.deinit() sleep_ms(rest_duration) def playSound(self, freq, tone_duration, rest_duration=0): beeper = PWM(self.PinBuzzer, freq, duty=self.duty[self.vol]) sleep_ms(tone_duration) beeper.deinit() sleep_ms(rest_duration) def random(self, x, y): return getrandbits(20) % (y - x + 1) + x def display_and_wait(self): self.display.show() timer_dif = int(1000 / self.frameRate) - ticks_diff( ticks_ms(), self.timer) if timer_dif > 0: sleep_ms(timer_dif) self.timer = ticks_ms()
from machine import Pin, ADC import utime # variabelen PIN_ADC = 36 # pin SVP # ADC pin initialiseren adc = ADC(Pin(PIN_ADC)) # 11 dB attenuation means full 0 - 3.3V range adc.atten(adc.ATTN_11DB) # min en max opslaan in calibratie bestand try: # lus meetwaarden while True: # ophalen meetwaarde licht = adc.read() # berekenen procent spanning = 3.3 * licht / 4095 # toon resultaat print('Meetwaarde: %d - Spanning: %0.2fV' % (licht, spanning)) # even wachten utime.sleep_ms(1000) except Exception as e: print('Probleem met bestand %s' % e) finally: adc.deinit()
class SystemVoltage(AbstractSystemSensor): """ Read the a voltage level by sampling the ADC on a pin connected to a voltage divider. As the Pycom expansion board is using Pin 16 for battery voltage, this is also used on other boards as kind of a convention. Implementation ============== Written by Dominik Kapusta <https://github.com/ayoy>. Thanks! Improved by Andreas Motl <https://github.com/amotl>. License ======= The MIT License (MIT) Copyright (c) 2018 Dominik Kapusta - https://kapusta.cc/2018/02/02/air-quality-monitor-revisited/ - https://github.com/ayoy/upython-aq-monitor/blob/lora/lib/adc.py Documentation ============= - https://docs.pycom.io/firmwareapi/pycom/machine/adc - https://docs.pycom.io/tutorials/all/adc More resources ============== - https://forum.pycom.io/topic/3776/adc-use-to-measure-battery-level-vin-level - https://github.com/hiveeyes/terkin-datalogger/issues/5 - https://community.hiveeyes.org/t/batterieuberwachung-voltage-divider-und-attenuation-fur-microypthon-firmware/2128 """ # How many times to sample the ADC for making a reading. adc_sample_count = const(1000) def __init__(self, settings): """ Initialized ADC unit. """ super().__init__(settings) # ADC Pin to sample from. self.pin = None # Main resistor value (R1). self.resistor_r1 = None # Resistor between input pin and ground (R2). self.resistor_r2 = None # Reference to platform ADC object. self.adc = None self.setup() def setup(self): """ - Configure the appropriate resistor values for computing the voltage. - Setup ADC for sampling. """ self.pin = self.settings.get('pin') self.resistor_r1 = self.settings.get('resistor_r1') self.resistor_r2 = self.settings.get('resistor_r2') self.adc_attenuation_db = self.settings.get('adc_attenuation_db', 6.0) self.reading_key = self.settings.get('type') assert type( self.pin) is str, 'VCC Error: Voltage divider ADC pin invalid' assert type( self.resistor_r1 ) is int, 'VCC Error: Voltage divider resistor value "resistor_r1" invalid' assert type( self.resistor_r2 ) is int, 'VCC Error: Voltage divider resistor value "resistor_r2" invalid' assert type( self.adc_attenuation_db ) is float, 'VCC Error: ADC attenuation value "adc_attenuation_db" invalid' # ADC channel used for sampling the raw value. from machine import ADC if self.adc_attenuation_db == 0.0: self.adc_atten = ADC.ATTN_0DB elif self.adc_attenuation_db == 2.5: self.adc_atten = ADC.ATTN_2_5DB elif self.adc_attenuation_db == 6.0: self.adc_atten = ADC.ATTN_6DB elif self.adc_attenuation_db == 11.0: self.adc_atten = ADC.ATTN_11DB else: raise ValueError( 'ADC attenuation value (adc_attenuation_db) not allowed : {}'. format(self.adc_attenuation_db)) if platform_info.vendor == platform_info.MICROPYTHON.Vanilla: from machine import Pin self.adc = ADC(Pin(int(self.pin[1:]))) elif platform_info.vendor == platform_info.MICROPYTHON.Pycom: self.adc = ADC(id=0) else: raise NotImplementedError('Reading the ADC is ' 'not implemented on this platform') def read(self): """Acquire voltage reading by sampling ADC.""" # Todo: Make attenuation factor configurable. from machine import ADC # Sample ADC a few times. adc_samples = [0.0] * self.adc_sample_count adc_mean = 0.0 i = 0 log.debug('Reading voltage level on pin {} with voltage divider {}/{}'. format(self.pin, self.resistor_r1, self.resistor_r2)) # read samples if platform_info.vendor == platform_info.MICROPYTHON.Vanilla: self.adc.atten(self.adc_atten) irq_state = disable_irq() while i < self.adc_sample_count: adc_samples[i] = self.adc.read() adc_mean += adc_samples[i] i += 1 enable_irq(irq_state) elif platform_info.vendor == platform_info.MICROPYTHON.Pycom: self.adc.init() adc_channel = self.adc.channel(attn=self.adc_atten, pin=self.pin) irq_state = disable_irq() while i < self.adc_sample_count: sample = adc_channel() adc_samples[i] = sample adc_mean += sample i += 1 enable_irq(irq_state) else: raise NotImplementedError('Reading the ADC is ' 'not implemented on this platform') adc_mean /= self.adc_sample_count adc_variance = 0.0 for sample in adc_samples: adc_variance += (sample - adc_mean)**2 adc_variance /= (self.adc_sample_count - 1) if platform_info.vendor == platform_info.MICROPYTHON.Vanilla: # FIXME: Make this work for vanilla ESP32. raw_voltage = 0.0 mean_voltage = 0.0 elif platform_info.vendor == platform_info.MICROPYTHON.Pycom: raw_voltage = adc_channel.value_to_voltage(4095) mean_voltage = adc_channel.value_to_voltage(int(adc_mean)) mean_variance = (adc_variance * 10**6) // (adc_mean**2) # log.debug("ADC readings. count=%u:\n%s" %(self.adc_sample_count, str(adc_samples))) log.debug("SystemVoltage: Mean of ADC readings (0-4095) = %15.13f" % adc_mean) log.debug( "SystemVoltage: Mean of ADC voltage readings (0-%dmV) = %15.13f" % (raw_voltage, mean_voltage)) log.debug("SystemVoltage: Variance of ADC readings = %15.13f" % adc_variance) log.debug( "SystemVoltage: 10**6*Variance/(Mean**2) of ADC readings = %15.13f" % mean_variance) resistor_sum = self.resistor_r1 + self.resistor_r2 if platform_info.vendor == platform_info.MICROPYTHON.Pycom: voltage_millivolt = (adc_channel.value_to_voltage( int(adc_mean))) * resistor_sum / self.resistor_r2 else: # FIXME: Make this work for vanilla ESP32. voltage_millivolt = 0.0 voltage_volt = voltage_millivolt / 1000.0 # Shut down ADC channel. if platform_info.vendor == platform_info.MICROPYTHON.Pycom: adc_channel.deinit() log.debug('Voltage level: {}'.format(voltage_volt)) reading = {self.reading_key: voltage_volt} return reading def power_off(self): """Shut down ADC.""" log.info('Turning off ADC') self.adc.deinit()
print(apin) apin = adc.channel(id=adc_channel) print(apin) apin = adc.channel(adc_channel, pin=adc_pin) print(apin) apin = adc.channel(id=adc_channel, pin=adc_pin) print(apin) print(apin.value() > 3000) print(apin() > 3000) # de-init must work apin.deinit() print(apin) adc.deinit() print(adc) print(apin) adc.init() print(adc) print(apin) apin.init() print(apin) print(apin() > 3000) # check for memory leaks... for i in range (0, 1000): adc = ADC() apin = adc.channel(adc_channel) # next ones should raise
np.set(0,P,0,0) time.sleep(0.1) np.set(0,0,0,0) time.sleep(0.1) # Wait for i in range (0,25): np.set(0, 2 * i, 0, 0) time.sleep(0.03) for i in range (26,100): np.set(0, 2 * i, 0, 0) time.sleep(0.0033) np.set(0,0,0,0) mqtt.disconnect() acs712.deinit()
def calibration(mode, vref): # mode => 0 adc calibration # mode => 1 sensor calibration from peripheral_query import _get_filtered_mvolts import time import ujson import uio from machine import Pin from machine import ADC from peripheral_query import GasData print('[4]===================') calibration_frequency = 1 # seconds calibration_times = 10 calibration_NH3 = [] calibration_SO2 = [] calibration_H2S = [] iter_calibration = 0 while iter_calibration < calibration_times: adc0 = ADC(id=0) outer_iter = 0 outer_iter_times = 20 outer_buff_NH3 = [] outer_buff_SO2 = [] outer_buff_H2S = [] while outer_iter < outer_iter_times: filtered_mvolts = _get_filtered_mvolts(adc0, vref) outer_buff_NH3.append(filtered_mvolts.NH3) outer_buff_SO2.append(filtered_mvolts.SO2) outer_buff_H2S.append(filtered_mvolts.H2S) outer_iter = outer_iter + 1 buff_nh3 = sum(outer_buff_NH3) / outer_iter_times buff_so2 = sum(outer_buff_SO2) / outer_iter_times buff_h2s = sum(outer_buff_H2S) / outer_iter_times print('[4]sample #: ' + ('%d' % (iter_calibration + 1)) + ' / ' + ('%d' % (calibration_times))) print('[4]sample NH3: ' + ('%.1f' % (buff_nh3))) print('[4]sample SO2: ' + ('%.1f' % (buff_so2))) print('[4]sample H2S: ' + ('%.1f' % (buff_h2s))) calibration_NH3.append(buff_nh3) calibration_SO2.append(buff_so2) calibration_H2S.append(buff_h2s) adc0.deinit() iter_calibration = iter_calibration + 1 time.sleep(calibration_frequency) cfg_nh3 = sum(calibration_NH3) / calibration_times cfg_so2 = sum(calibration_SO2) / calibration_times cfg_h2s = sum(calibration_H2S) / calibration_times with uio.open('/flash/configure.json', 'r', encoding="utf-8") as handle: psd_json = ujson.load(handle) if mode == 0: psd_json["calibration"]["sensor_nh3"]["bias"] = round(cfg_nh3, 1) psd_json["calibration"]["sensor_so2"]["bias"] = round(cfg_so2, 1) psd_json["calibration"]["sensor_h2s"]["bias"] = round(cfg_h2s, 1) print('[4]Calibration finished...') print('[4]NH3 bias: ' + ('%.1f' % (cfg_nh3))) print('[4]SO2 bias: ' + ('%.1f' % (cfg_so2))) print('[4]H2S bias: ' + ('%.1f' % (cfg_h2s))) elif mode == 1: psd_json["calibration"]["sensor_nh3"]["i0"] = round( (cfg_nh3 - psd_json["calibration"]["sensor_nh3"]["bias"]) / 624, 1) psd_json["calibration"]["sensor_so2"]["i0"] = round( (cfg_so2 - psd_json["calibration"]["sensor_so2"]["bias"]) / 624, 1) psd_json["calibration"]["sensor_h2s"]["i0"] = round( (cfg_h2s - psd_json["calibration"]["sensor_h2s"]["bias"]) / 624, 1) print('[4]Calibration finished...') print('[4]NH3 zero-drift: ' + ('%.1f' % ( (cfg_nh3 - psd_json["calibration"]["sensor_nh3"]["bias"]) / 624))) print('[4]SO2 zero-drift: ' + ('%.1f' % ( (cfg_so2 - psd_json["calibration"]["sensor_so2"]["bias"]) / 624))) print('[4]H2S zero-drift: ' + ('%.1f' % ( (cfg_h2s - psd_json["calibration"]["sensor_h2s"]["bias"]) / 624))) with uio.open('/flash/configure.json', 'w', encoding="utf-8") as handle: json_r_str = ujson.dumps(psd_json) handle.write(json_r_str) print('[4]Configure file written...')
class SystemBatteryLevel: """ Read the battery level by sampling the ADC on a pin connected to a voltage divider. As the Pycom expansion board is using Pin 16, this is also used on other boards as kind of a convention. Implementation ============== Written by Dominik Kapusta <https://github.com/ayoy>. Thanks! Improved by Andreas Motl <https://github.com/amotl>. License ======= The MIT License (MIT) Copyright (c) 2018 Dominik Kapusta - https://kapusta.cc/2018/02/02/air-quality-monitor-revisited/ - https://github.com/ayoy/upython-aq-monitor/blob/lora/lib/adc.py Documentation ============= - https://docs.pycom.io/firmwareapi/pycom/machine/adc - https://docs.pycom.io/tutorials/all/adc More resources ============== - https://forum.pycom.io/topic/3776/adc-use-to-measure-battery-level-vin-level - https://github.com/hiveeyes/hiveeyes-micropython-firmware/issues/5 - https://community.hiveeyes.org/t/batterieuberwachung-voltage-divider-und-attenuation-fur-microypthon-firmware/2128 """ # How many times to sample the ADC for making a reading. adc_sample_count = const(1000) def __init__(self): """ Initialized ADC unit. """ # ADC Pin to sample from. self.pin = None # Main resistor value (R1). self.resistor_r1 = None # Resistor between input pin and ground (R2). self.resistor_r2 = None # Reference to platform ADC object. self.adc = None def setup(self, settings): self.pin = settings.get('sensors.system.vcc.pin') self.resistor_r1 = settings.get('sensors.system.vcc.resistor_r1') self.resistor_r2 = settings.get('sensors.system.vcc.resistor_r2') assert type( self.pin) is str, 'VCC Error: Voltage divider ADC pin invalid' assert type( self.resistor_r1 ) is int, 'VCC Error: Voltage divider resistor value "resistor_r1" invalid' assert type( self.resistor_r2 ) is int, 'VCC Error: Voltage divider resistor value "resistor_r2" invalid' # ADC channel used for sampling the raw value. from machine import ADC try: self.adc = ADC(id=0) except TypeError: from machine import Pin self.adc = ADC(Pin(self.pin)) def read(self): """ Acquire vbatt reading by sampling ADC. """ # Power on ADC. self.adc.init() log.debug('Reading battery level on pin {} with voltage divider {}/{}'. format(self.pin, self.resistor_r1, self.resistor_r2)) # Sample ADC a few times. # Todo: Make attenuation factor configurable. from machine import ADC adc_channel = self.adc.channel(attn=ADC.ATTN_6DB, pin=self.pin) adc_samples = [0.0] * self.adc_sample_count adc_mean = 0.0 i = 0 irq_state = disable_irq() while i < self.adc_sample_count: sample = adc_channel() adc_samples[i] = sample adc_mean += sample i += 1 enable_irq(irq_state) adc_mean /= self.adc_sample_count adc_variance = 0.0 for sample in adc_samples: adc_variance += (sample - adc_mean)**2 adc_variance /= (self.adc_sample_count - 1) raw_voltage = adc_channel.value_to_voltage(4095) mean_voltage = adc_channel.value_to_voltage(int(adc_mean)) mean_variance = (adc_variance * 10**6) // (adc_mean**2) # log.debug("ADC readings. count=%u:\n%s" %(self.adc_sample_count, str(adc_samples))) log.debug( "SystemBatteryLevel: Mean of ADC readings (0-4095) = %15.13f" % adc_mean) log.debug( "SystemBatteryLevel: Mean of ADC voltage readings (0-%dmV) = %15.13f" % (raw_voltage, mean_voltage)) log.debug("SystemBatteryLevel: Variance of ADC readings = %15.13f" % adc_variance) log.debug( "SystemBatteryLevel: 10**6*Variance/(Mean**2) of ADC readings = %15.13f" % mean_variance) resistor_sum = self.resistor_r1 + self.resistor_r2 voltage_millivolt = (adc_channel.value_to_voltage( int(adc_mean))) * resistor_sum / self.resistor_r2 voltage_volt = voltage_millivolt / 1000.0 # Shut down ADC channel. adc_channel.deinit() log.debug('Battery level: {}'.format(voltage_volt)) reading = {'system.voltage': voltage_volt} return reading def power_off(self): """ Shut down ADC. """ log.info('Turning off ADC') self.adc.deinit()
# # Copyright (c) 2006-2019, RT-Thread Development Team # # SPDX-License-Identifier: MIT License # # Change Logs: # Date Author Notes # 2019-06-13 SummerGift first version # from machine import ADC # Import the ADC class from machine # adc channel 5 : PB23 # adc channel 6 : PB24 # adc channel 7 : PB25 # adc channel 8 : PB26 adc = ADC( "adc", 5 ) # Creates an ADC object that currently uses the 5 channel(PB23) of an ADC device name "adc" value = ( adc.read() - 8192.0 ) / 8192 * 2.25 / 1.2 + 1.584 # Gets the ADC object sampling value and change to voltage value print("Voltage Value: %.3f" % value) # print voltage value adc.deinit() # Close ADC object adc.init(5) # Open and reconfigure the ADC object
class gameOGO(): max_vol = 6 duty = {0: 0, 1: 0.05, 2: 0.1, 3: 0.5, 4: 1, 5: 2, 6: 70} tones = { 'c4': 262, 'd4': 294, 'e4': 330, 'f4': 349, 'f#4': 370, 'g4': 392, 'g#4': 415, 'a4': 440, "a#4": 466, 'b4': 494, 'c5': 523, 'c#5': 554, 'd5': 587, 'd#5': 622, 'e5': 659, 'f5': 698, 'f#5': 740, 'g5': 784, 'g#5': 831, 'a5': 880, 'b5': 988, 'c6': 1047, 'c#6': 1109, 'd6': 1175, ' ': 0 } def __init__(self): # True = SPI display, False = I2C display self.ESP32 = True self.useSPI = True self.displayTimer = ticks_ms() self.vol = int(self.max_vol) seed(ticks_us()) self.btnU = 1 << 1 self.btnL = 1 << 2 self.btnR = 1 << 3 self.btnD = 1 << 4 self.btnA = 1 << 5 self.btnB = 1 << 6 self.btnMenu = 1 << 7 self.btnVol = 1 << 8 self.btnSel = 1 << 9 self.btnSt = 1 << 10 self.btnUval = 0 self.btnDval = 0 self.btnLval = 0 self.btnRval = 0 self.btnAval = 0 self.btnBval = 0 self.btnMenuval = 0 self.btnVolval = 0 self.btnSelval = 0 self.btnStval = 0 self.frameRate = 30 self.maxBgm = 1 self.bgm = 1 self.songIndex = 0 self.songStart = -1 self.songEnd = -2 self.songLoop = -3 self.silence = 0 self.songSpeed = 1 self.timeunit = 1 self.notes = False self.songBuf = [] self.Btns = 0 self.lastBtns = 0 self.dac_pin = Pin(25, Pin.OUT, value=1) # switch speaker on self.PinBuzzer = Pin(26, Pin.OUT) self.beeper = PWM(self.PinBuzzer, 500, duty=0) self.beeper2 = PWM(self.PinBuzzer, 500, duty=0) self.timerInitialized = False self.tft = display.TFT() self.tft.init(self.tft.ILI9341, width=240, height=320, speed=40000000, backl_pin=14, backl_on=1, miso=19, mosi=23, clk=18, cs=5, dc=21, hastouch=False) self.tft.clear(self.tft.BLACK) self.tft.orient(self.tft.LANDSCAPE_FLIP) self.screenW, self.screenH = self.tft.screensize() ''' fonts available in ili9341 tft.FONT_Small, 8x12 tft.FONT_Default, 13x13 tft.FONT_7seg, 18x31 tft.FONT_Ubuntu, 15x16 tft.FONT_Comic, 25x28 tft.FONT_Tooney, 32x37 tft.FONT_Minya, 20x24 ''' self.tft.font(self.tft.FONT_Ubuntu, rotate=0) self.PinBtnA = Pin(BUTTON_A_PIN, Pin.IN, Pin.PULL_UP) self.PinBtnB = Pin(BUTTON_B_PIN, Pin.IN, Pin.PULL_UP) self.PinBtnMenu = Pin(BUTTON_MENU_PIN, Pin.IN, Pin.PULL_UP) self.PinBtnVol = Pin(BUTTON_VOLUME_PIN, Pin.IN, Pin.PULL_UP) self.PinBtnSel = Pin(BUTTON_SELECT_PIN, Pin.IN, Pin.PULL_UP) self.PinBtnSt = Pin(BUTTON_START_PIN, Pin.IN) self.adcX = ADC(BUTTON_JOY_X_PIN) self.adcY = ADC(BUTTON_JOY_Y_PIN) #self.adc = ADC(PADDLE_PIN) self.adcX.atten(ADC.ATTN_11DB) self.adcY.atten(ADC.ATTN_11DB) #self.adc.atten(ADC.ATTN_11DB) def deinit(self): #self.adc.deinit() self.beeper.deinit() self.beeper2.deinit() self.adcX.deinit() self.adcY.deinit() self.tft.deinit() self.songIndex = 0 if self.timerInitialized: self.timer.deinit() def getPaddle(self): return 512 # ESP32 - 142 to 3155 # return max ( min (int (self.adc.read() / 2.935) - 48, 1023),0) def pressed(self, btn): return (self.Btns & btn) def justPressed(self, btn): return (self.Btns & btn) and not (self.lastBtns & btn) def justReleased(self, btn): return (self.lastBtns & btn) and not (self.Btns & btn) def getBtn(self): self.btnAval = not self.PinBtnA.value() self.btnBval = not self.PinBtnB.value() self.btnMenuval = not self.PinBtnMenu.value() self.btnVolval = not self.PinBtnVol.value() self.btnSelval = not self.PinBtnSel.value() self.btnStval = not self.PinBtnSt.value() val = self.adcX.read() self.btnLval = 1 if val > 2500 else 0 self.btnRval = 1 if 1500 < val < 2000 else 0 val = self.adcY.read() self.btnUval = 1 if val > 2500 else 0 self.btnDval = 1 if 1500 < val < 2000 else 0 self.lastBtns = self.Btns self.Btns = 0 self.Btns = self.Btns | self.btnUval << 1 | self.btnLval << 2 | self.btnRval << 3 | self.btnDval << 4 | self.btnAval << 5 | self.btnBval << 6 self.Btns = self.Btns | self.btnMenuval << 7 | self.btnVolval << 8 | self.btnSelval << 9 | self.btnStval << 10 return self.Btns def setVol(self): if self.pressed(self.btnVol): if self.justPressed(self.btnU): self.vol = min(self.vol + 1, self.max_vol) self.playTone('c4', 100) return True elif self.justPressed(self.btnD): self.vol = max(self.vol - 1, 0) self.playTone('d4', 100) return True return False def setFrameRate(self): if self.pressed(self.btnSel): if self.justPressed(self.btnU): self.frameRate = self.frameRate + 5 if self.frameRate < 120 else 5 self.playTone('e4', 100) return True elif self.justPressed(self.btnD): self.frameRate = self.frameRate - 5 if self.frameRate > 5 else 120 self.playTone('f4', 100) return True return False def center_msg(self, msg, color_fg, color_bg): self.tft.set_bg(color_bg) self.tft.textClear((self.screenW - self.tft.textWidth(msg)) // 2, self.screenH // 2, msg, color_bg) self.tft.text((self.screenW - self.tft.textWidth(msg)) // 2, self.screenH // 2, msg, color_fg) def display_msg(self, x, y, msg, color_fg, color_bg): self.tft.set_bg(color_bg) self.tft.textClear(x, y, msg, color_bg) self.tft.text(x, y, msg, color_fg) def display_vol(self): fontW, fontH = self.tft.fontSize() self.tft.rect(self.screenW - fontW * self.max_vol, 0, self.max_vol * fontW, fontH, self.tft.GREEN, self.tft.BLACK) self.tft.rect(self.screenW - fontW * self.max_vol + 1, 1, self.vol * fontW - 2, fontH - 2, self.tft.RED, self.tft.RED) def playTone(self, tone, tone_duration, rest_duration=0): self.beeper = PWM(self.PinBuzzer, self.tones[tone], self.duty[self.vol]) sleep_ms(tone_duration) self.beeper.deinit() sleep_ms(rest_duration) def playSound(self, freq, tone_duration, rest_duration=0): self.beeper = PWM(self.PinBuzzer, freq, self.duty[self.vol]) sleep_ms(tone_duration) self.beeper.deinit() sleep_ms(rest_duration) def handleInterrupt(self, timer): self.beeper2.deinit( ) # note has been played logn enough, now stop sound if self.songBuf[self.songIndex] == self.songLoop: self.songIndex = 3 # repeat from first note if self.songBuf[self.songIndex] >= 0: if self.songBuf[self.songIndex] == 0: self.beeper2 = PWM(self.PinBuzzer, 100, 0) elif self.notes: self.beeper2 = PWM(self.PinBuzzer, self.tones[self.songBuf[self.songIndex]], self.duty[self.vol]) else: self.beeper2 = PWM(self.PinBuzzer, self.songBuf[self.songIndex], self.duty[self.vol]) self.timer.init(period=int(self.songBuf[self.songIndex + 1] * self.timeunit * self.songSpeed), mode=Timer.ONE_SHOT, callback=self.handleInterrupt) self.songIndex += 2 def startSong(self, songBuf=None): if self.bgm: if songBuf != None: self.songBuf = songBuf if self.songBuf[0] != self.songStart: print("Cannot start Song, Invalid songBuf") return False self.notes = self.songBuf[1] self.timeunit = self.songBuf[2] self.songIndex = 3 if not self.timerInitialized: self.timerInitialized = True self.timer = Timer(1) self.timer.init(period=100, mode=Timer.ONE_SHOT, callback=self.handleInterrupt) def stopSong(self): self.songIndex = 0 def random(self, x, y): return randint(x, y) def wait(self): timer_dif = int(1000 / self.frameRate) - ticks_diff( ticks_ms(), self.displayTimer) if timer_dif > 0: sleep_ms(timer_dif) self.displayTtimer = ticks_ms()
def peripheral_query(is_init, p_out_ctrla, p_out_ctrlb): import pycom import time import socket import binascii import struct import gc import sys import os import uio import ujson from machine import UART from machine import ADC from machine import I2C from machine import SPI from machine import Pin from tsl2591 import TSL2591 with uio.open('/flash/configure.json', 'r', encoding="utf-8") as hdl: parsed_json = ujson.load(hdl) sht31 = parsed_json["firmware"]["sht31"] bias_nh3 = parsed_json["calibration"]["sensor_nh3"]["bias"] bias_so2 = parsed_json["calibration"]["sensor_so2"]["bias"] bias_h2s = parsed_json["calibration"]["sensor_h2s"]["bias"] di_nh3 = parsed_json["calibration"]["sensor_nh3"]["di"] di_so2 = parsed_json["calibration"]["sensor_so2"]["di"] di_h2s = parsed_json["calibration"]["sensor_h2s"]["di"] i0_nh3 = parsed_json["calibration"]["sensor_nh3"]["i0"] i0_so2 = parsed_json["calibration"]["sensor_so2"]["i0"] i0_h2s = parsed_json["calibration"]["sensor_h2s"]["i0"] vref = parsed_json["calibration"]["vref"] p_data = PeripheralData() print('[2]===================') adc0 = ADC(id=0) outer_iter = 0 outer_iter_times = 20 outer_buff_NH3 = [] outer_buff_SO2 = [] outer_buff_H2S = [] while outer_iter < outer_iter_times: filtered_mvolts = _get_filtered_mvolts(adc0, vref) outer_buff_NH3.append(filtered_mvolts.NH3) outer_buff_SO2.append(filtered_mvolts.SO2) outer_buff_H2S.append(filtered_mvolts.H2S) outer_iter = outer_iter + 1 buff_nh3 = sum(outer_buff_NH3) / outer_iter_times buff_so2 = sum(outer_buff_SO2) / outer_iter_times buff_h2s = sum(outer_buff_H2S) / outer_iter_times buff_nh3 = round((buff_nh3 - bias_nh3 - i0_nh3 * 47 * 0.624) * 50 / (di_nh3 * 47 * 0.624), 1) adc0_str = '%.1f' % ((buff_nh3)) p_data.NH3 = (buff_nh3) print('[2]NH3: ' + adc0_str) buff_so2 = round((buff_so2 - bias_so2 - i0_so2 * 47 * 0.624) * 20 / (di_so2 * 47 * 0.624), 1) adc1_str = '%.1f' % ((buff_so2)) p_data.SO2 = ((buff_so2)) print('[2]SO2: ' + adc1_str) buff_h2s = round((buff_h2s - bias_h2s - i0_h2s * 47 * 0.624) * 50 / (di_h2s * 47 * 0.624), 1) adc2_str = '%.1f' % ((buff_h2s)) p_data.H2S = ((buff_h2s)) print('[2]H2S: ' + adc2_str) adc0.deinit() time.sleep(0.01) adc3 = ADC(id=0) # create an ADC object apin3 = adc3.channel(pin='P16') # create an analog pin on P16 adc3.vref(vref) adc3_str = '%.2f' % (apin3() * 220 / 4096) p_data.current = apin3() * 220 / 4096 print('[2]Current@5V: ' + adc3_str + 'mA') adc3.deinit() p_out_ctrla.value(0) p_out_ctrlb.value(1) uart_mul = UART(1, baudrate=9600, pins=('P3', 'P4')) time.sleep(0.1) co2_set = is_init while co2_set == 0: uart_mul.write('K 2\r\n') time.sleep(0.05) dumm = uart_mul.readline() if dumm == bytes([]): print('[2]CO2 sensor no respose!') break else: dumm_str = dumm.decode('utf-8') if dumm_str == ' K 00002\r\n': print('[2]CO2 sensor polling set successfully...') time.sleep(0.05) co2_set = 1 else: print('[2]CO2 sensor polling resetting...') time.sleep(0.05) uart_mul.write('M 00006\r\n') time.sleep(0.05) dumm_str = uart_mul.readall().decode('utf-8') if dumm_str == ' M 00006\r\n': print('[2]CO2 sensor key set successfully...') time.sleep(0.05) time.sleep(0.05) number = 0 while number != 18: dummy = uart_mul.readall() uart_mul.write('Q\r\n') time.sleep(0.1) number = uart_mul.any() data_str = uart_mul.readall().decode("utf-8") print('[2]CO2_Filtered: ' + data_str[4:8]) print('[2]CO2_Instant: ' + data_str[12:16]) p_data.CO2 = int(data_str[4:8]) * 100 - 1600 print('[2]CO2: ' + ('%d' % (p_data.CO2))) i2c = I2C(0, I2C.MASTER) i2c.init(I2C.MASTER, baudrate=100000, pins=('P9', 'P10')) time.sleep(0.05) #print(i2c.scan()) if sht31 == 0: i2c.writeto(0x40, bytes([0xF3])) time.sleep(0.1) temperature_data = i2c.readfrom(0x40, 3) #print(temperature_data) time.sleep(0.1) temperature_value = _get_temperature_from_buffer(temperature_data) p_data.temp = temperature_value time.sleep(0.1) i2c.writeto(0x40, bytes([0xF5])) time.sleep(0.05) humidity_data = i2c.readfrom(0x40, 3) humidity_value = _get_humidity_from_buffer(humidity_data) p_data.humd = humidity_value humidity_value_str = '%.2f' % humidity_value temperature_value_str = '%.2f' % temperature_value print('[2]Humidity: ' + humidity_value_str) print('[2]Temperature: ' + temperature_value_str) else: i2c.writeto(0x44, bytes([0x24, 0x00])) time.sleep(0.02) combined_data = i2c.readfrom(0x44, 6) temperature_value = _get_sht31_temp_from_buffer(combined_data) p_data.temp = temperature_value humidity_value = _get_sht31_humidity_from_buffer(combined_data) p_data.humd = humidity_value humidity_value_str = '%.2f' % humidity_value temperature_value_str = '%.2f' % temperature_value print('[2]Humidity (SHT31): ' + humidity_value_str) print('[2]Temperature (SHT31): ' + temperature_value_str) lux_sensor = TSL2591(i2c) lux_flt = lux_sensor.lux p_data.lux = lux_flt print('[2]Light: ' + '%.2f' % lux_flt + 'lux') uart_mul = UART(1, baudrate=9600, pins=('P3', 'P4')) p_out_ctrla.value(1) p_out_ctrlb.value(0) time.sleep(0.1) ggflag = 0 ddflag = 0 while ggflag == 0 or ddflag == 0: while uart_mul.any() == 0: time.sleep(0.1) nmealine_bytes = uart_mul.readall() #print(nmealine_bytes) time.sleep(0.1) nmealine_all = nmealine_bytes.decode('utf-8') nmealine_all_split = nmealine_all.split('\r\n') for nmealine in nmealine_all_split: if (nmealine[0:6] == '$GNGGA') and (len(nmealine.split(',')) >= 15) and (ggflag == 0): nmea_fields = nmealine.split(',') #print(nmea_fields) print('[2]Time: ' + nmea_fields[1]) if nmea_fields[1] != '': p_data.time = float(nmea_fields[1]) print('[2]Lat: ' + nmea_fields[2] + nmea_fields[3]) if nmea_fields[2] != '': p_data.lat = float(nmea_fields[2]) if nmea_fields[3] == 'S': p_data.lat *= -1 print('[2]Lon: ' + nmea_fields[4] + nmea_fields[5]) if nmea_fields[4] != '': p_data.Lon = float(nmea_fields[4]) if nmea_fields[5] == 'W': p_data.lon *= -1 print('[2]Fix: ' + nmea_fields[6]) print('[2]#Sat: ' + nmea_fields[7]) print('[2]HDOP: ' + nmea_fields[8]) print('[2]Alt: ' + nmea_fields[9]) if nmea_fields[9] != '': p_data.alt = float(nmea_fields[9]) ggflag = 1 elif (nmealine[0:6] == '$GNRMC') and (len(nmealine.split(',')) >= 13) and (ddflag == 0): nmea_fields = nmealine.split(',') print('[2]Date: ' + nmea_fields[9]) if nmea_fields[9] != '': p_data.date = int(nmea_fields[9]) ddflag = 1 dummy = uart_mul.readall() p_data_bytes = PeripheralBytes(p_data) print('[2]===================') time.sleep(0.01) gc.collect() print(gc.mem_free()) return p_data_bytes