From ea4bd872bc868784081b8a149e9f3789bf781591 Mon Sep 17 00:00:00 2001 From: rbaron Date: Thu, 11 Feb 2021 17:59:35 +0100 Subject: [PATCH] Simple PWM-based square wave works --- README.md | 17 +++++++++---- code/parasite/lib/parasite/pwm.cpp | 4 +-- code/parasite/src/main.cpp | 16 ++++++------ resources.md | 39 +++++++++++++++++++++++++++++- 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index cb5c5db..3486070 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,19 @@ A low power soil moisture sensor based on the nRF52840. # TODO -* Hook square wave generator to the protoboard sensor circuit -* Make the protoboard sensor work +* Implement ADC; check out air/water range (using protoboard) +* Figure out how to calibrate the ADC when running from different voltages, as the battery discharges * Implement deep sleep -* Measure power consumption in deep sleep -* Measure power consumption in transmission +* Implement BLE advertising with moisture, battery level +* Measure current in deep sleep +* Measure current in operation (ADC + BLE adversiting) +* Test with a range of 2-5V input. Disconnect from USB and monitor using a serial post. Use the bench power supply to power Vcc with variable voltage. *DO NOT CONNECT VCC FROM THE USB-TO-SERIAL BOARD!** * Test with a coin cell +* Figure out a way for people to configure the device with a custom name. Idea: BLE service (this is what my [hacked xiaomi temp sensor](https://github.com/atc1441/ATC_MiThermometer) does) +* Figure out how OTA works (if at all) over BLE +* Design new board using the nrf52 instead of esp32 # Done -* Simple PWM square wave generator \ No newline at end of file +* Simple PWM square wave generator +* Hook square wave generator to the protoboard sensor circuit +* Make the protoboard sensor work \ No newline at end of file diff --git a/code/parasite/lib/parasite/pwm.cpp b/code/parasite/lib/parasite/pwm.cpp index 6aaf11e..9214049 100644 --- a/code/parasite/lib/parasite/pwm.cpp +++ b/code/parasite/lib/parasite/pwm.cpp @@ -22,11 +22,11 @@ void SetupSquareWave(double frequency, int pin_number) { const int max_count = 16e6 / frequency; // Since we want a duty cycle of 0.5, we flip the PVM output when the counter - // reaches kPWMMaxCounter / 2/; + // reaches kPWMMaxCounter / 2; const int flip_at_count = max_count / 2; HwPWM0.addPin(pin_number); - HwPWM0.setClockDiv(PWM_PRESCALER_PRESCALER_DIV_1); + HwPWM0.setClockDiv(kPWMFrequencyPrescale); HwPWM0.setMaxValue(max_count); HwPWM0.writePin(pin_number, flip_at_count); HwPWM0.begin(); diff --git a/code/parasite/src/main.cpp b/code/parasite/src/main.cpp index 24ab5ff..b81afaa 100644 --- a/code/parasite/src/main.cpp +++ b/code/parasite/src/main.cpp @@ -5,21 +5,23 @@ constexpr int kLED1Pin = 17; constexpr int kLED2Pin = 18; constexpr int kPWMPin = 19; +constexpr int kSensAnalogPin = 4; // AIN2 +constexpr int kDischargeEnablePin = 16; constexpr double kPWMFrequency = 500000; void setup() { Serial.begin(9600); pinMode(kLED1Pin, OUTPUT); - pinMode(kLED2Pin, OUTPUT); + pinMode(kDischargeEnablePin, OUTPUT); parasite::SetupSquareWave(kPWMFrequency, kPWMPin); + digitalWrite(kDischargeEnablePin, HIGH); + + analogReference(AR_VDD4); } void loop() { - Serial.print("Hello, world\n"); - digitalWrite(kLED1Pin, LOW); - digitalWrite(kLED2Pin, LOW); - delay(500); - digitalWrite(kLED1Pin, HIGH); - digitalWrite(kLED2Pin, HIGH); + int sens_val = analogRead(kSensAnalogPin); + Serial.printf("Val: %d\n", sens_val); + digitalToggle(kLED1Pin); delay(500); } \ No newline at end of file diff --git a/resources.md b/resources.md index d10fc2f..ecc50f7 100644 --- a/resources.md +++ b/resources.md @@ -103,4 +103,41 @@ The [SoftDevice S132 spec](https://infocenter.nordicsemi.com/index.jsp?topic=%2F # PWM * [HardwarePWM.cpp](https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/a86fd9f36c88db96f676cead1e836377a37c7b05/cores/nRF5/HardwarePWM.cpp#L112) by Adafruit is a good reference. [Servo.c](https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/4d703b6f38262775863a16a603c12aa43d249f04/libraries/Servo/src/nrf52/Servo.cpp#L154) uses it. * [nrf52832 pwm spec](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fpwm.html) -* [nrf5 SDK PWM reference](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v11.0.0%2Fgroup__nrf__pwm__hal.html) HAL => Hardware Abstraction Layer? \ No newline at end of file +* [nrf5 SDK PWM reference](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v11.0.0%2Fgroup__nrf__pwm__hal.html) HAL => Hardware Abstraction Layer? + +# Analog to digital converter (ADC) +* In nrf52-land, the ADC is called [SSADC](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.0.0%2Fgroup__nrf__adc.html) +* Example in the sdk: in `examples/peripheral/saadc/main.c` +* [Docs from Adafruit](https://learn.adafruit.com/bluefruit-nrf52-feather-learning-guide/nrf52-adc). It uses Arduino's `analogRead`. + +## Resoultion +The default resolution is 10 bits (1024 values), + +## Reference value + The default reference is an internally supplied 3.6V. It seems like we woulld only be able to read values up to 3.6V. This might be enough if we're using a CR2032 coin cell, but might not if we use a LiPo (4.2V fully charged). + +**Question**: what happens if Vcc < 3.6? + +There is a possibility of using Vcc as a reference. Then I imagine 0 -> 0V; 1024 -> Vcc. This might be exactly what we want: +In a PWM positive pulse, our RC_parasitic will rise to 0.63Vcc in R*C_para time. If we use Vcc as a reference for the ADC, I think we "cancel out" the Vcc factor. + +* How adafruit uses the Vcc reference: [link](https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/cores/nRF5/wiring_analog_nRF52.c#L76) +* How arduino-nRF5 uses the Vcc refenrece: [link](https://github.com/sandeepmistry/arduino-nRF5/blob/master/cores/nRF5/wiring_analog_nRF52.c#L98) + +So in Arduino land, using AR_VDD4 does all we need: use nrf's SAADC_CH_CONFIG_REFSEL_VDD1_4 (Vcc/4 ref) and a gain of 4 (SAADC_CH_CONFIG_GAIN_Gain1_4). +While connected via USB, with: +``` +analogReference(AR_VDD4); +int sens_val = analogRead(kSensAnalogPin); +``` +I'm getting ~680 when in the air; ~65 while holding the sensor. The default resolution is 10 bits, so 1024 -> 3.3V. On the scope, I'm reading the sensor output value to be 2.16V. This matches the value I'm reading: 1024/3.3 * 2.15 = 667. Nice. + +# Battery +* [CR2032 datasheet](https://data.energizer.com/pdfs/cr2032.pdf) + * 235 mAh (from 3.0V to 2.0V) + * Typical discharge current: 0.19 mA -> 1200 hours + +# Battery monitoring +* Good post on how to measure lipo batteries: [link](https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/measuring-lithium-battery-voltage-with-nrf52#:~:text=To%20reduce%20the%20leakage%20current,of%2040%20us%2C%20see%20here.) + +# OTA \ No newline at end of file