I have finally got round to putting my draft code online (GitHub). This is probably the weakest part of the project at the moment. In this post I will concentrate on the issues with the sensor code. Here is the full main.c:
// ------- Preamble -------- //
#include <avr/io.h> // Defines pins, ports, etc
#include <util/delay.h> // Functions to waste time
#include <stdlib.h>
#include "pinDefines.h"
#include "piezo.h"
#include "nrf24l01.h"
#include <avr/interrupt.h>
volatile uint16_t adcValue = 0;
volatile uint16_t middleValue = 511;
volatile uint16_t highValue = 520;
volatile uint16_t lowValue = 500;
volatile uint16_t noiseVolume = 0;
volatile uint8_t padding = 20;
volatile uint8_t ADCCount = 0;
void sendSignal(void){
initNRF24L01();
//Reset MOSI pin (PB0) to allow signal to be sent again
RF_DDR &= ~(1<<RF_MOSI);
RF_PORT|= (1<<RF_MOSI);
reset();
uint8_t W_buffer;
W_buffer=0x01;
int retries; //Send signal multiple times
for (retries=0;retries<5;retries++){
transmit_payload(W_buffer);
}
}
ISR(ADC_vect){
//Shift result left by 8 bits as using left align - allows full 10 bits to be captured
adcValue = ADCH;
// moving average -- tracks sensor's bias voltage
middleValue = adcValue + middleValue - ((middleValue - 8) >> 4);
// moving averages for positive and negative parts of signal
if (adcValue > (middleValue >> 4)) {
highValue = adcValue + highValue - ((highValue - 8) >> 4);
}
if (adcValue < (middleValue >> 4)) {
lowValue = adcValue + lowValue - ((lowValue - 8) >> 4);
}
// "padding" provides a minimum value for the noise volume
noiseVolume = highValue - lowValue + padding;
// Now check to see if ADC value above or below thresholds
// Comparison with >> 4 b/c EWMA is on different scale
if (adcValue < ((middleValue - noiseVolume) >> 4)) {
sendSignal();
}
else if (adcValue > ((middleValue + noiseVolume) >> 4)) {
sendSignal();
}
}
int main(void)
{
initSPI();
initADC();
initNRF24L01();
while(1)
{
if (adcValue>2000){
sendSignal();
}
}
return 0;
}
ADC ISR is intended to use an exponentially weighted moving average for assessing when the ADC value is significantly high enough. The key parts were taken from the excellent book Make: AVR Programming by Elliott Williams (available on amazon.co.uk) which was my gateway drug into this hobby and which I really can't recommend highly enough.
The ADC is running in free-running mode. However, as I haven't yet looked at how to put the attiny into sleep mode whilst keeping the ADC running, I have fudged the main loop at the moment by just including a conditional statement that can never be met. This is something I hope to correct over the next week as it is clearly not an efficient way to program.
The other thing you will notice is that the data sent is just a random buffer. Eventually I will send a separate identification code for each sensor so that the bracelet will be able to determine which one has been triggered. However, for reasons I can't quite work out the data received by the bracelet is not the same as that being sent so this is again an issue that needs looking at.
The bracelet is another hornet's nest of patchy coding and I will turn my attention to this once I am happy with the sensor side. The list of things to do seems to be getting longer!
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.