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
from machine import I2C import pycom from network import LoRa from machine import ADC import socket import machine import ubinascii import tsl2591 # Ambient Light Sensor library file #----------------------------------------------------------------------------------------- #| Setup ADC Configuration: #| Initialize ADC using configured Vref value (1108 mV) and 12 bits of resolution #----------------------------------------------------------------------------------------- adc = ADC(0) adc.vref(1108) adc.init(bits=12) #----------------------------------------------------------------------------------------- #| Initialize Sensor Pinouts - Both GPIO and ADC #| #| Dual JSN-SR04T 2.0 Ultrasonic Sensors (Which sensor is #1 vs #2 does not matter): #| - Sensor 1: Trigger => Pin 21 ("trigger_1"); used as 3.3V GPIO Output from uC to sensor #| - Sensor 1: Echo => Pin 22 ("echo_1"); used as 3.3V (Down from 5V) Input to UC from sensor #| - Sensor 2: Trigger => Pin 23 ("trigger_2"); used as 3.3V GPIO Output from uC to sensor #| - Sensor 2: Echo => Pin 18 ("echo_2"); used as 3.3V (Down from 5V) Input to UC from sensor #| #| TSL2591 Ambient Light Sensor (initialize using "tsl = tsl2591.Tsl2591(0)" statement, #| pins provided below only for reference): #| - SCL (for I2C) => Pin 9; Configured in included tsl2591.py file, not here #| - SDA (for I2C) => Pin 10; Configured in included tsl2591.py file, not here #|
# # 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
from machine import ADC ''' ADC (analog to digital conversion) ADC is available on a dedicated pin. Note that input voltages on the ADC pin must be between 0v and 1.0v. Use the machine.ADC class: ''' adc = ADC(0) adc.init(bits=9) # set 9 bit return values (returned range 0-511) # set 11dB input attentuation (voltage range roughly 0.0v - 3.6v) adc_v = adc.channel(pin='P13', attn=ADC.ATTN_11DB) value = adc_v.value() voltage = adc_v.voltage() # 0-4095 across voltage range 0.0v - 1.0v print("ADC vegetronix value:" + str(value)) print("ADC vegetronix voltage:" + str(voltage)) ''' ADC.atten(attenuation) This method allows for the setting of the amount of attenuation on the input of the ADC. This allows for a wider possible input voltage range, at the cost of accuracy (the same number of bits now represents a wider range). The possible attenuation options are: ADC.ATTN_0DB: 0dB attenuation, gives a maximum input voltage of 1.00v - this is the default configuration ADC.ATTN_2_5DB: 2.5dB attenuation, gives a maximum input voltage of approximately 1.34v ADC.ATTN_6DB: 6dB attenuation, gives a maximum input voltage of approximately 2.00v ADC.ATTN_11DB: 11dB attenuation, gives a maximum input voltage of approximately 3.6v Warning
sample_buffer = [None] * sample_N #0-99 #https://forum.pycom.io/topic/2384/measuring-current-with-the-adc #recommended max f_s = 6kHz f_s = 4000 adc_res = 4096 int_fft_flag = 0 t_sec_wait = 15 t_wait = f_s * t_sec_wait #https://forum.pycom.io/topic/170/lopy-wipy-2-esp32-specs-and-performance/8 adc_mic = ADC(0) adc_mic.init(bits=12) adc_mic_c = adc_mic.channel(pin='P13', attn=ADC.ATTN_11DB) #================================== # Reduce ADC Res #================================== # adc_mic = ADC(bits=9) # adc_mic.init() # adc_mic_c = adc_mic.channel(pin='P13', attn=ADC.ATTN_11DB) # adc_res = 512 #================================== # Reduce FFT Res for Display #==================================
client = MQTTClient(MQTT_CLIENT_ID, MQTT_PROVIDER, user=MQTT_USERNAME, password=MQTT_PW, port=MQTT_PORT) time.sleep_ms(200) client.connect() for i in range(0, 5): pycom.rgbled(0x000055) #Dark Blue - Connected to MQTT time.sleep_ms(100) pycom.rgbled(0x0) #LED OFF time.sleep_ms(100) adc = ADC() # Create an ADC object adc.init(bits=ADC_BITS) # Enables the ADC block with 12 bits width samples apin = adc.channel( pin='P16', attn=ADC.ATTN_11DB ) # Create an analog pin on P16, with 11 db Attenuation so the V range is 0 to 3.3V #Main Cycle while 1: val = 0 for i in range(0, MAX_SAMPLES): val += apin.value() val = (val / MAX_SAMPLES ) #Mean of 1000 Samples to reduce the noise/glitches val = (3.3 / ((2**ADC_BITS) - 1)) * val #Scale/Mapping of the value to voltage #3.3V is the maximum value of the input for a 11dB Attenuation
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()
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()
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 try: adc = ADC(bits=17) except:
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 try: adc = ADC(bits=17) except: