Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor US driver in order to dont block the interrupt #1

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 133 additions & 60 deletions LotMonitor/ATtiny85/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,33 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#ifndef AVR_STUDIO
#include "light_ws2812.h" // https://github.com/cpldcpu/light_ws2812
#endif // AVR_STUDIO
#include "main.h"

#define ONBOARD_LED PB1
#define SRF05_ECHO PB2
#define SRF05_TRIGGER PB3
// WS2819_DATA PB4 // See Makefile WS2812_PIN

#define INTERRUPT_DIV 10

#define INTERRUPT_DIV 10
#define ECHO_TIMEOUT 517 // 30000us / 58us
#define TRIGGER_TIMER_FREQ 160 // 100Hz
#define ECHO_TIMER_FREQ 116 // 58us interruption

#define WS2819_STRIPE_LEN 5
#define WS2819_BRIGHTNESS 25 // percent [optional, comment for full brightness]
#define WS2819_BRIGHTNESS 100 // percent [optional, comment for full brightness]

struct cRGB led[WS2819_STRIPE_LEN+1]; // one more to prevent array overflow

volatile int32_t interrupt_cnt = INTERRUPT_DIV;
volatile int32_t SRF05_distance_cm = 0;
// one more to prevent array overflow
;
volatile int32_t last_25cm_flicker = 0;
volatile struct US_variables SRF05_values;


struct cRGB led[WS2819_STRIPE_LEN+1];
//---------
// This function lights a bar in the given RGB and length.
//----------
Expand All @@ -49,116 +57,181 @@ void inline setLEDS(uint8_t r, uint8_t g, uint8_t b, uint8_t c) {
//---------
// This function turns all LEDs off
//----------
void inline allOFF() {
void inline allOFF(uint8_t update_available) {
//----------
allColor(color_black);
if (update_available == False) //WS2812 library is dis-activating interrupt when change the color, creating error in the US measurements
{
allColor(color_black);
}

}

//---------
// This function lights all LEDs to a given color
//----------
void inline allColor(struct cRGB color) {
//----------
setLEDS(color.r,color.g,color.b, WS2819_STRIPE_LEN);


setLEDS(color.r,color.g,color.b, WS2819_STRIPE_LEN);

}

//---------
// This function lights a bar in the given color and length.
//----------
void inline barColor(struct cRGB color, int bars) {
void inline barColor(struct cRGB color, int bars,uint8_t update_available) {
//----------
setLEDS(color.r,color.g,color.b, bars);
if (update_available == False)
{
setLEDS(color.r,color.g,color.b, bars);
}
}


//---------
// This function is executed 100 times per sec by timer interupt (See TCCR0B)
// This function is executed 100 times per sec by timer interrupt (See TCCR0B)
//----------
ISR(TIM0_COMPA_vect) {
//----------

switch(SRF05_values.state)
{
case trigger:

if(SRF05_values.trigger_elapsed >= INTERRUPT_DIV ) // software divisor to trigger measure every 10 ms
{
SRF05_values.updating_measures = True;
PORTB |= (1 << SRF05_TRIGGER);
set_timer0_preescaler_and_compare_registers(TIM0_PREESCALER_8,ECHO_TIMER_FREQ); //set prescaler to 8 (CLK=16MHz/8/116=97.17241Hz, 58us)
SRF05_values.state = waiting_for_echo;
}
else
{
SRF05_values.updating_measures = False;
SRF05_values.trigger_elapsed++ ;
}
break;

case waiting_for_echo:
PORTB &= ~(1 << SRF05_TRIGGER); //deactivate trigger pin and wait for echo signal. Maximum waiting time 30 ms
if(!(PINB & (1 << SRF05_ECHO)))
{
if(SRF05_values.echo_elapsed >= ECHO_TIMEOUT)
{

SRF05_values.state = time_out;
}
else
{
SRF05_values.echo_elapsed++;
}
}
else
{
SRF05_values.state = echo_received;
}
break;

case echo_received:
PINB |= (1 << ONBOARD_LED); //With logic analyzer you can check that the measurement are corrects connecting in PB1
SRF05_values.echo_total_time++;

if(SRF05_values.echo_total_time < ECHO_TIMEOUT)
{
if(!(PINB & (1 << SRF05_ECHO)))
{
SRF05_values.echo_buffered_total_time = SRF05_values.echo_total_time;
SRF05_values.echo_elapsed = 0;
SRF05_values.trigger_elapsed = 0;
SRF05_values.echo_total_time = 0;
set_timer0_preescaler_and_compare_registers(TIM0_PREESCALER_1024,TRIGGER_TIMER_FREQ); //set prescaler to 1024 (CLK=16MHz/1024/160=97.68Hz, 0.010s)
SRF05_values.state = trigger;
}
}
else
{
SRF05_values.state = time_out;
}


break;

case time_out:

SRF05_values.echo_elapsed = 0;
SRF05_values.trigger_elapsed = 0;
SRF05_values.echo_total_time = 0;
SRF05_values.echo_buffered_total_time = 0xffff;
set_timer0_preescaler_and_compare_registers(TIM0_PREESCALER_1024,TRIGGER_TIMER_FREQ); //set prescaler to 1024 (CLK=16MHz/1024/160=97.68Hz, 0.010s)
SRF05_values.state = trigger;


break;
}

if (++interrupt_cnt > INTERRUPT_DIV) // skip some interrupts b/c SRF05
{ // handles max. 20 trigger/sec.
interrupt_cnt = 0; // INTERRUPT_DIV=10 does 10/sec

last_25cm_flicker = !last_25cm_flicker; // See "distance_cm < 26" in main
// while(1) loop
PORTB |= (1 << SRF05_TRIGGER); // Trigger SRF05 Measurement
_delay_us(10);
PORTB &= ~(1 << SRF05_TRIGGER);

uint32_t echo_time_us = 0;
uint32_t echo_wait_us = 300; // timeout to wait for echo in us

while ( !(PINB & (1 << SRF05_ECHO)) & (echo_wait_us > 0) ) { // Wait 4 echo
_delay_us(1); // max. 300us
--echo_wait_us;
}

if (echo_wait_us) { // we got an echo
PORTB |= (1 << ONBOARD_LED); // turn on led (just for fun)

while ( (PINB & (1 << SRF05_ECHO)) ) { // count echo HIGH time
_delay_us(1);
++echo_time_us;
}
} else {
allColor(color_blue); // no echo, sensor gone?
}

if (echo_time_us > 17450) { // 17450 / 58 = 300.86cm, to be ignored
SRF05_distance_cm = 0;
} else {
SRF05_distance_cm = echo_time_us / 58;
}

PORTB &= ~(1 << ONBOARD_LED); // turn off led
}
}

//---------
// This function is main entry point
//----------
int main(void) {
//----------

SRF05_values.echo_elapsed = 0;
SRF05_values.state = trigger;
SRF05_values.trigger_elapsed = 0;
SRF05_values.echo_total_time = 0;
SRF05_values.echo_buffered_total_time = 0xffff;

// Setup Data-Direction-Register
DDRB &= ~(1 << SRF05_ECHO); // set data direction register for HY-SRF05 echo port
PORTB &= ~(1 << SRF05_ECHO); // No internal pullup

DDRB |= (1 << ONBOARD_LED); // set data direction register for ONBOARD_LED as output
PORTB &= ~(1 << ONBOARD_LED);
DDRB |= (1 << SRF05_TRIGGER); // set data direction register for HY-SRF05 trigger port

TCCR0A |= _BV(WGM01); // set timer counter mode to CTC
TCCR0B |= _BV(CS02)|_BV(CS00); // set prescaler to 1024 (CLK=16MHz/1024/160=97.68Hz, 0.010s)
OCR0A = 160; // set Timer's counter max value
TIMSK |= _BV(OCIE0A); // enable Timer CTC interrupt


set_timer0_preescaler_and_compare_registers(TIM0_PREESCALER_1024,TRIGGER_TIMER_FREQ); //set prescaler to 1024 (CLK=16MHz/1024/160=97.68Hz, 0.010s)

sei(); //enable global interrupt

while(1)
{
int distance_cm = SRF05_distance_cm; // snapshot b/c volatile may change
uint16_t distance_cm = SRF05_values.echo_buffered_total_time; // snapshot b/c volatile may change
int bars;

if ((distance_cm < 1) | (distance_cm > 300)) { // Switch stripe off if
allOFF(); // invalid (0) distance or
allOFF(SRF05_values.updating_measures); // invalid (0) distance or
} else { // greater than 3m.
if (distance_cm < 26 ) { // less than 26cm, flicker
_delay_ms(100); //will be optimized
if ( last_25cm_flicker ) { // all leds like crazy
allOFF(); // based on volatile
} else { // last_25cm_flicker.
barColor(color_red, WS2819_STRIPE_LEN); // See ISR(TIM0_COMPA_vect)
last_25cm_flicker = 0;
allOFF(SRF05_values.updating_measures); // based on volatile
} else {
last_25cm_flicker = 1 ; // last_25cm_flicker.
barColor(color_red, WS2819_STRIPE_LEN,SRF05_values.updating_measures); // See ISR(TIM0_COMPA_vect)
}
} else { // Distance 26cm-3m:
if (distance_cm < 101) { // more red leds if closer
bars = (100 - distance_cm) / 15; // than 1m till 26cm. One
barColor(color_red, ++bars); // additional led per 15cm
barColor(color_red, ++bars,SRF05_values.updating_measures); // additional led per 15cm
} else { // less green leds if closer
bars = (distance_cm-100)/40; // than 3m till 1m. One led
barColor(color_green, ++bars); // less per 40cm.
barColor(color_green, ++bars,SRF05_values.updating_measures); // less per 40cm.
}
}
}
}
}


void set_timer0_preescaler_and_compare_registers(uint8_t preescaler,uint8_t compare)
{
TCCR0B &= TIM0_NO_CLOCK;
TCNT0 = 0 ;
OCR0A = compare;
TCCR0B |= preescaler;
}
37 changes: 36 additions & 1 deletion LotMonitor/ATtiny85/main.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,46 @@
// cRGB is internal grb !

#include "light_ws2812.h"

#define TIM0_NO_CLOCK (~(1<<CS02 | 1<<CS01 | 1<<CS00))
#define TIM0_PREESCALER_1 1<<CS00
#define TIM0_PREESCALER_8 1<<CS01
#define TIM0_PREESCALER_64 1<<CS01 | 1<<CS00
#define TIM0_PREESCALER_256 1<<CS02
#define TIM0_PREESCALER_1024 1<<CS02 | 1<<CS00

static const struct cRGB color_black = { 0, 0, 0 };
static const struct cRGB color_red = { 0, 255, 0 };
static const struct cRGB color_green = { 255, 0, 0 };
static const struct cRGB color_blue = { 0, 0, 255 };
static const struct cRGB color_white = { 255, 255, 255 };

void allOFF();
void allOFF(uint8_t update_available);
void all(uint8_t r, uint8_t g, uint8_t b);
void allRGB(uint8_t r, uint8_t g, uint8_t b);
void allColor(struct cRGB color);

void set_timer0_preescaler_and_compare_registers(uint8_t preescaler,uint8_t compare);

#define True 1
#define False 0


enum US_states
{
trigger,
waiting_for_echo,
echo_received,
time_out,

};

struct US_variables
{
uint16_t trigger_elapsed;
uint16_t echo_elapsed;
uint16_t echo_total_time;
uint16_t echo_buffered_total_time;
uint8_t updating_measures;
enum US_states state;
}
72 changes: 0 additions & 72 deletions LotMonitor/ATtiny85/main.hex

This file was deleted.

Loading