Sensor Watch 0.0.2
A board replacement for the classic Casio F-91W wristwatch, powered by a Microchip SAM L22 microcontroller.
|
This section covers functions related to the SAM L22's analog-to-digital converter, as well as configuring and reading values from the five analog-capable pins on the 9-pin connector. More...
Enumerations | |
enum | watch_adc_reference_voltage { ADC_REFERENCE_INTREF = 0 , ADC_REFERENCE_VCC_DIV1POINT6 , ADC_REFERENCE_VCC_DIV2 , ADC_REFERENCE_VCC } |
Functions | |
void | watch_enable_adc (void) |
Enables the ADC peripheral. You must call this before attempting to read a value from an analog pin. | |
void | watch_enable_analog_input (const uint8_t pin) |
Configures the selected pin for analog input. | |
uint16_t | watch_get_analog_pin_level (const uint8_t pin) |
Reads an analog value from one of the pins. | |
void | watch_set_analog_num_samples (uint16_t samples) |
Sets the number of samples to accumulate when measuring a pin level. Default is 16. | |
void | watch_set_analog_sampling_length (uint8_t cycles) |
Sets the length of time spent sampling, which allows measurement of higher impedance inputs. Default is 1. | |
void | watch_set_analog_reference_voltage (watch_adc_reference_voltage reference) |
Selects the reference voltage to use for analog readings. Default is ADC_REFERENCE_VCC. | |
uint16_t | watch_get_vcc_voltage (void) |
Returns the voltage of the VCC supply in millivolts (i.e. 3000 mV == 3.0 V). If running on a coin cell, this will be the battery voltage. | |
void | watch_disable_analog_input (const uint8_t pin) |
Disables the analog circuitry on the selected pin. | |
void | watch_disable_adc (void) |
Disables the ADC peripheral. | |
This section covers functions related to the SAM L22's analog-to-digital converter, as well as configuring and reading values from the five analog-capable pins on the 9-pin connector.
void watch_disable_adc | ( | void | ) |
Disables the ADC peripheral.
void watch_disable_analog_input | ( | const uint8_t | pin | ) |
Disables the analog circuitry on the selected pin.
pin | One of pins A0-A4. |
void watch_enable_analog_input | ( | const uint8_t | pin | ) |
Configures the selected pin for analog input.
pin | One of pins A0-A4. |
uint16_t watch_get_analog_pin_level | ( | const uint8_t | pin | ) |
Reads an analog value from one of the pins.
pin | One of pins A0-A4. |
uint16_t watch_get_vcc_voltage | ( | void | ) |
Returns the voltage of the VCC supply in millivolts (i.e. 3000 mV == 3.0 V). If running on a coin cell, this will be the battery voltage.
Unlike other ADC functions, this function does not return a raw value from the ADC, but rather scales it to an actual number of millivolts. This is because the ADC doesn't let us measure VCC per se; it instead lets us measure VCC / 4, and we choose to measure it against the internal reference voltage of 1.024 V. In short, the ADC gives us a number that's complicated to deal with, so we just turn it into a useful number for you :)
void watch_set_analog_num_samples | ( | uint16_t | samples | ) |
Sets the number of samples to accumulate when measuring a pin level. Default is 16.
samples | A power of 2 <= 1024. Specifically: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 or 1024. Any other value will be ignored. |
The SAM L22's ADC has a resolution of 12 bits. By default, the watch configures the ADC to take 16 samples of the analog input and accumulate them in the result register; this effectively gives us a 16-bit resolution, at the cost of taking 16 ADC cycles to complete a measurement. If you are measuring a slowly changing signal like a thermistor output or an ambient light sensor this is probably fine, even desirable. If you are measuring something a bit more fast-paced, like an analog accelerometer, you may wish to exchange precision for speed. In this case you may call this function to configure the ADC to accumulate fewer samples. HOWEVER! Note that this may change the range of values returned from watch_get_analog_pin_level:
void watch_set_analog_reference_voltage | ( | watch_adc_reference_voltage | reference | ) |
Selects the reference voltage to use for analog readings. Default is ADC_REFERENCE_VCC.
reference | One of ADC_REFERENCE_VCC, ADC_REFERENCE_VCC_DIV1POINT6, ADC_REFERENCE_VCC_DIV2 or ADC_REFERENCE_INTREF. |
In order to turn an analog voltage into a 16-bit integer, the ADC needs to compare the measured voltage to a reference point. For example, if you were powering the watch with VCC == 3.0V and you had two 10K resistors connected in series from 3V to GND, you could expect to get 3 volts when you measure the top of the voltage divider, 0 volts at the bottom, and 1.5 volts in the middle. If you read these values uising a reference voltage of ADC_REFERENCE_VCC, the top value would be about 65535, the bottom about 0, and the middle about 32768. However! If we used ADC_REFERENCE_VCC_DIV2 as our reference, we would expect to get 65535 both at the top and the middle, because the largest value the ADC can measure in this configutation is 1.5V (VCC / 2).
By changing the reference voltage from ADC_REFERENCE_VCC to ADC_REFERENCE_VCC_DIV1POINT6 or ADC_REFERENCE_VCC_DIV2, you can get more resolution when measuring small voltages (i.e. a phototransistor circuit in low light).
There is also a special reference voltage called ADC_REFERENCE_INTREF. The SAM L22's Supply Controller provides a selectable voltage reference (by default, 1.024 V) that you can select as a reference voltage for ADC conversions. Unlike the three references we talked about in the last paragraph, this reference voltage does not depend on VCC, which makes it very useful for measuring the battery voltage (since you can't really compare VCC to itself). You can change the INTREF voltage to 2.048 or 4.096 V by poking at the supply controller's VREF register, but the watch library does not support this use case.
void watch_set_analog_sampling_length | ( | uint8_t | cycles | ) |
Sets the length of time spent sampling, which allows measurement of higher impedance inputs. Default is 1.
cycles | The number of ADC cycles to sample, between 1 and 64. |
To measure an analog value, the SAM L22 must charge a capacitor to the analog voltage presented at the input. This takes time. Importantly, the higher the input impedance, the more time this takes. As a basic example: if you are using a thermistor tied to VCC to measure temperature, the capacitor has to charge through the thermistor. The higher the resistor value, the higher the input impedance, and the more time we need to allow for the measurement. By default, the ADC is configured to run on a 500 kHz clock with a sample time of one cycle. This is appropriate for an input impedance up to about 28kΩ. Setting the sampling time to 4 cycles allows for an input impedance up to 123kΩ. Setting the sampling time to the maximum of 64 cycles theoretically allows for input impedance up to 2 MΩ. (I based these numbers on the calculator in the linked blog post; it also has a ton of great info on the SAM D21 ADC, which is similar to the SAM L22's).