Use custom ADC interface using AVR flags

This commit is contained in:
2025-05-14 14:36:41 +02:00
parent cbf42aae0a
commit 1a10abc4d6
6 changed files with 67 additions and 13 deletions
+7 -4
View File
@@ -27,9 +27,10 @@ CXXFLAGS = $(CFLAGS) -fno-exceptions -fpermissive -std=gnu++11
LDFLAGS = -Wall -Os -mmcu=$(MCU) -Wl,--gc-sections
LIBS = -lm
SRCS_CPP = main.cpp moisture.cpp
HDRS = moisture.h config.h
OBJS = $(addprefix $(OBJ_DIR)/, $(SRCS_CPP:.cpp=.o))
SRCS_C = adc.c moisture.c main.c
#SRCS_CPP = main.cpp
HDRS = moisture.h config.h adc.h
OBJS = $(addprefix $(OBJ_DIR)/, $(SRCS_CPP:.cpp=.o) $(SRCS_C:.c=.o))
CORE_C_SRCS = \
wiring.c \
@@ -44,7 +45,6 @@ CORE_CPP_SRCS = \
Stream.cpp \
HardwareSerial.cpp \
HardwareSerial0.cpp \
main.cpp
CORE_SRCS = $(addprefix $(ARDUINO_CORE_PATH)/, $(CORE_C_SRCS) $(CORE_CPP_SRCS))
CORE_OBJS = $(patsubst $(ARDUINO_CORE_PATH)/%.c,$(CORE_DIR)/%.o,$(filter %.c,$(CORE_SRCS))) \
@@ -66,6 +66,9 @@ $(ELF_TARGET): $(OBJS) $(CORE_LIB)
$(CORE_LIB): $(CORE_OBJS)
$(AR) rcs $@ $^
$(OBJ_DIR)/%.o: %.c $(HDRS) Makefile
$(CC) $(CFLAGS) -c $< -o $@
$(OBJ_DIR)/%.o: %.cpp $(HDRS) Makefile
$(CXX) $(CXXFLAGS) -c $< -o $@
+27
View File
@@ -0,0 +1,27 @@
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
void adcInit(void) {
// Set reference voltage to AVcc (REFS0 = 1, REFS1 = 0)
ADMUX = (1 << REFS0);
// Enable ADC and set prescaler to 128 (for 16 MHz clock, gives 125 kHz ADC clock)
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
}
uint16_t adcRead(uint8_t channel) {
// Select ADC pin (A0-A7) by setting MUX bits in ADMUX
// Pins A6 and A7 would make an 8 sensor array possible (for large vases).
// Achievable only when using the 328p as a DIP, through port C (PC6, PC7)
ADMUX = (ADMUX & 0xF8) | (channel & 0x07);
// Start conversion
ADCSRA |= (1 << ADSC);
// Wait for conversion to complete (ADSC becomes '0' when done)
while (ADCSRA & (1 << ADSC));
// Read ADC (reading order: ADCL --> ADCH)
return ADC;
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef ADC_H
#define ADC_H
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
void adcInit(void);
uint16_t adcRead(uint8_t channel);
#endif
+13 -2
View File
@@ -1,7 +1,18 @@
#ifndef CONFIG_H
#define CONFIG_H
#define MOISTURE_SENSOR_A0 A0
#define SENSOR_READINGS 3
#define MOISTURE_SENSOR_A0 PC0
#define MOISTURE_SENSOR_A1 PC1
#define MOISTURE_SENSOR_A2 PC2
#define MOISTURE_SENSOR_A3 PC3
#define MOISTURE_SENSOR_A4 PC4
#define MOISTURE_SENSOR_A5 PC5
// NOTE: PC6 PC7 are not accessible by default on Arduino Uno R3
// You need to use the ATMega328p on a custom PCB and use pins 1 and 2
#define MOISTURE_SENSOR_A6 PC6
#define MOISTURE_SENSOR_A7 PC7
#define SENSOR_READINGS 5
#endif
+4 -3
View File
@@ -1,4 +1,3 @@
#include <Arduino.h>
#include <stdint.h>
#include <stdbool.h>
#include <avr/sleep.h>
@@ -26,17 +25,19 @@ void enterSleep(void) {
}
void setup(void) {
Serial.begin(9600);
initMoistureSensor();
watchdogs();
}
int main(void) {
setup();
while(true) {
if (readSensors) {
int16_t result = readMoisture();
if (result != -1) {
Serial.println(result);
//Serial.println(result);
readSensors = false;
}
}
@@ -1,10 +1,10 @@
#include <Arduino.h>
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "moisture.h"
#include "config.h"
#include "adc.h"
static int16_t moistureReadingSum = 0;
static int8_t moistureReadingCount = 0;
@@ -12,7 +12,8 @@ static int8_t moistureReadingCount = 0;
volatile bool readSensors = false;
void initMoistureSensor(void) {
pinMode(MOISTURE_SENSOR_A0, INPUT);
DDRC &= ~(1 << MOISTURE_SENSOR_A0); // set as input
PORTC &= ~(1 << MOISTURE_SENSOR_A0); //disable pullup
}
void triggerSensorRead(void) {
@@ -23,13 +24,13 @@ int16_t readMoisture(void) {
if (!readSensors)
return -1;
moistureReadingSum += analogRead(MOISTURE_SENSOR_A0);
adcInit();
moistureReadingSum += adcRead(MOISTURE_SENSOR_A0);
moistureReadingCount++;
//TODO: implement variance check (if over a certain variance discard measurements for this cicle)
if (moistureReadingCount >= SENSOR_READINGS) {
int16_t average = moistureReadingSum / SENSOR_READINGS;
//Serial.println(average);
moistureReadingSum = 0;
moistureReadingCount = 0;
readSensors = false;