Merge branch 'master' into radio

This commit is contained in:
Rihards Skuja 2018-01-02 14:31:14 +02:00
commit 446f85b05a
No known key found for this signature in database
GPG Key ID: 53FA13A3F7F8571B
14 changed files with 361 additions and 262 deletions

9
include/common.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef COMMON_H
#define COMMON_H
#define SET(X, Y) X |= (1 << Y)
#define CLR(X, Y) X &= ~(1 << Y)
#define CHK(X, Y) X & (1 << Y)
#define TOG(X, Y) X ^= (1 << Y)
#endif /* COMMON_H */

View File

@ -1,15 +0,0 @@
#ifndef PORTS_H
#define PORTS_H
/* DS18B20+ is configured in DS18B20 library */
/* Signal LED */
#define LED_1 PD3
/* Servo motors */
#define SERVO_L_PIN PB1
#define SERVO_L OCR1A
#define SERVO_R_PIN PB2
#define SERVO_R OCR1B
#endif

10
include/led.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef LED_H
#define LED_H
#define LED_DDR DDRD
#define LED_1_BIT PD3
#define LED_2_BIT PD4
void init_leds(void);
#endif /* LED_H */

View File

@ -3,15 +3,6 @@
#include <stdint.h> #include <stdint.h>
#define SET(PORT, PIN) (PORT |= (1 << PIN))
#define CLR(PORT, PIN) (PORT &= (~(1 << PIN)))
#define CHK(PORT, PIN) (PORT & (1 << PIN))
#define TOG(PORT, PIN) (PORT ^= (1 << PIN))
void init_led(void);
void init_pwm(void);
void read_temp(void); void read_temp(void);
void run_servos(void);
uint16_t read_adc(uint8_t channel);
#endif #endif

21
include/servos.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef SERVOS_H
#define SERVOS_H
#define SERVO_DDR DDRD
#define SERVO_L_REG OCR0B
#define SERVO_R_REG OCR0A
#define SERVO_L_BIT PD5
#define SERVO_R_BIT PD6
#define SERVO_MIN 930 // (us). Go backwards
#define SERVO_MAX 1930 // (us). Go forwards
#define SERVO_MID (SERVO_MIN + SERVO_MAX) / 2 // Stop
#define PWM_PERIOD 16384 // (1000000 / F_CPU) * PRESCALER * 256) / F_CPU (us)
#define US2TIMER0(us) (255 * (uint32_t)us) / PWM_PERIOD
void init_servos(void);
void run_servos(void);
#endif /* SERVOS_H */

45
include/sonar.h Normal file
View File

@ -0,0 +1,45 @@
#ifndef SONAR_H
#define SONAR_H
#include "common.h"
// Trigger
#define TRIG_DDR DDRC
#define TRIG_PORT PORTC
#define TRIG_PIN PINC
#define TRIG_BIT PC4
// Echo
#define ECHO_DDR DDRC
#define ECHO_PORT PORTC
#define ECHO_PIN PINC
#define ECHO_BIT PC5
#define SPEED_OF_SOUND 343 // (m/s)
#define US_PER_CM 58 // Time for sound to travel distance of 1cm
#define MAX_SONAR_RANGE 8 // Trigger + echo (m)
#define DELAY_BETWEEN_TESTS 500 // Timeout for return signal
#define TIMER_MAX 65535 // Depends on the timer used
#define CYCLES_PER_US F_CPU / 1000000
#define SONAR_TIMEOUT (F_CPU * MAX_SONAR_RANGE) / SPEED_OF_SOUND
#define TRIG_ERROR -1
#define ECHO_ERROR -2
#define TRIG_INPUT_MODE() CLR(TRIG_DDR, TRIG_BIT)
#define TRIG_OUTPUT_MODE() SET(TRIG_DDR, TRIG_BIT)
#define TRIG_LOW() CLR(TRIG_PORT, TRIG_BIT)
#define TRIG_HIGH() SET(TRIG_PORT, TRIG_BIT)
#define ECHO_INPUT_MODE() CLR(ECHO_DDR, ECHO_BIT)
#define ECHO_OUTPUT_MODE() SET(ECHO_DDR, ECHO_BIT)
#define ECHO_LOW() CLR(ECHO_PORT, ECHO_BIT)
#define ECHO_HIGH() SET(ECHO_PORT, ECHO_BIT)
void init_sonar(void);
void trigger_sonar(void);
unsigned int read_sonar(void);
#endif /* SONAR_H */

View File

@ -18,14 +18,11 @@ References:
#include <avr/io.h> #include <avr/io.h>
//setup connection #define DS18B20_PORT PORTC
#define DS18B20_DDR DDRC
#define DS18B20_PIN PINC
#define DS18B20_BIT PC0
#define DS18B20_PORT PORTD
#define DS18B20_DDR DDRD
#define DS18B20_PIN PIND
#define DS18B20_DQ PD7
//commands
#define DS18B20_CMD_CONVERTTEMP 0x44 #define DS18B20_CMD_CONVERTTEMP 0x44
#define DS18B20_CMD_RSCRATCHPAD 0xbe #define DS18B20_CMD_RSCRATCHPAD 0xbe
#define DS18B20_CMD_WSCRATCHPAD 0x4e #define DS18B20_CMD_WSCRATCHPAD 0x4e
@ -41,7 +38,7 @@ References:
//stop any interrupt on read //stop any interrupt on read
#define DS18B20_STOPINTERRUPTONREAD 1 #define DS18B20_STOPINTERRUPTONREAD 1
//functions
uint8_t ds18b20_reset(void); uint8_t ds18b20_reset(void);
void ds18b20_writebit(uint8_t bit); void ds18b20_writebit(uint8_t bit);
uint8_t ds18b20_readbit(void); uint8_t ds18b20_readbit(void);

View File

@ -1,144 +0,0 @@
/*
ds18b20 lib 0x02
copyright (c) Davide Gironi, 2012
Released under GPLv3.
Please refer to LICENSE file for licensing information.
*/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "ds18b20.h"
/*
* ds18b20 init
*/
uint8_t ds18b20_reset()
{
uint8_t i;
//low for 480us
DS18B20_PORT &= ~(1 << DS18B20_DQ); //low
DS18B20_DDR |= (1 << DS18B20_DQ); //output
_delay_us(480);
//release line and wait for 60uS
DS18B20_DDR &= ~(1 << DS18B20_DQ); //input
_delay_us(60);
//get value and wait 420us
i = (DS18B20_PIN & (1 << DS18B20_DQ));
_delay_us(420);
//return the read value, 0=ok, 1=error
return i;
}
/*
* write one bit
*/
void ds18b20_writebit(uint8_t bit)
{
//low for 1uS
DS18B20_PORT &= ~(1 << DS18B20_DQ); //low
DS18B20_DDR |= (1 << DS18B20_DQ); //output
_delay_us(1);
//if we want to write 1, release the line (if not will keep low)
if (bit)
DS18B20_DDR &= ~(1 << DS18B20_DQ); //input
//wait 60uS and release the line
_delay_us(60);
DS18B20_DDR &= ~(1 << DS18B20_DQ); //input
}
/*
* read one bit
*/
uint8_t ds18b20_readbit(void)
{
uint8_t bit = 0;
//low for 1uS
DS18B20_PORT &= ~(1 << DS18B20_DQ); //low
DS18B20_DDR |= (1 << DS18B20_DQ); //output
_delay_us(1);
//release line and wait for 14uS
DS18B20_DDR &= ~(1 << DS18B20_DQ); //input
_delay_us(14);
//read the value
if (DS18B20_PIN & (1 << DS18B20_DQ))
bit = 1;
//wait 45uS and return read value
_delay_us(45);
return bit;
}
/*
* write one byte
*/
void ds18b20_writebyte(uint8_t byte)
{
uint8_t i = 8;
while (i--) {
ds18b20_writebit(byte & 1);
byte >>= 1;
}
}
/*
* read one byte
*/
uint8_t ds18b20_readbyte(void)
{
uint8_t i = 8, n = 0;
while (i--) {
n >>= 1;
n |= (ds18b20_readbit() << 7);
}
return n;
}
/*
* get temperature
*/
double ds18b20_gettemp()
{
uint8_t temperature_l;
uint8_t temperature_h;
double retd = 0;
#if DS18B20_STOPINTERRUPTONREAD == 1
cli();
#endif
ds18b20_reset(); //reset
ds18b20_writebyte(DS18B20_CMD_SKIPROM); //skip ROM
ds18b20_writebyte(DS18B20_CMD_CONVERTTEMP); //start temperature conversion
while (!ds18b20_readbit()); //wait until conversion is complete
ds18b20_reset(); //reset
ds18b20_writebyte(DS18B20_CMD_SKIPROM); //skip ROM
ds18b20_writebyte(DS18B20_CMD_RSCRATCHPAD); //read scratchpad
//read 2 byte from scratchpad
temperature_l = ds18b20_readbyte();
temperature_h = ds18b20_readbyte();
#if DS18B20_STOPINTERRUPTONREAD == 1
sei();
#endif
//convert the 12 bit value obtained
retd = ((temperature_h << 8) + temperature_l) * 0.0625;
return retd;
}

9
src/led.c Normal file
View File

@ -0,0 +1,9 @@
#include <avr/io.h>
#include "common.h"
#include "led.h"
void init_leds(void)
{
SET(LED_DDR, LED_1_BIT);
SET(LED_DDR, LED_2_BIT);
}

View File

@ -1,36 +1,21 @@
#include <avr/io.h> #include <avr/io.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <util/delay.h> #include <util/delay.h>
#include "ds18b20.h" #include "temperature.h"
#include "led.h"
#include "servos.h"
#include "sonar.h"
#include "nrf24.h" #include "nrf24.h"
#include "io.h"
#include "main.h" #include "main.h"
#ifdef DEBUG #ifdef DEBUG
#include "debug.h" #include "debug.h"
#endif /* DEBUG */ #endif /* DEBUG */
void init_pwm(void) #ifndef F_CPU
{ #define F_CPU 1000000UL
DDRB |= 1 << SERVO_L_PIN | 1 << SERVO_R_PIN; #endif
/* Phase Correct PWM; Set/clear on Compare Match when down/up-counting */
TCCR1A |= 1 << WGM11 | 1 << COM1A1 | 1 << COM1B1;
/* "Clear Timer on Compare match" mode; Prescaler = 1 */
TCCR1B |= 1 << WGM12 | 1 << WGM13 | 1 << CS10;
ICR1 = F_CPU / 50 - 1; // 50Hz required by servos
}
void init_led(void)
{
DDRD |= 1 << LED_1;
}
void init_adc(void)
{
ADCSRA |= 1 << ADPS0 | 1 << ADPS1; // Prescaler = 8 => ADC clock = 125Hz
ADMUX |= 1 << REFS0; // AVcc with external cap as reference voltage
ADCSRA |= 1 << ADEN | 1 << ADSC;
}
void read_temp(void) void read_temp(void)
{ {
@ -39,61 +24,22 @@ void read_temp(void)
sei(); sei();
for (;;) { for (;;) {
d = ds18b20_gettemp(); d = ds18b20_gettemp();
if (d >= 21) if (d >= 23)
SET(PORTD, LED_1); ;
else else
CLR(PORTD, LED_1); ;
_delay_ms(500); _delay_ms(500);
} }
} }
void run_servos(void)
{
/* Stop */
SERVO_L = 1500;
SERVO_R = 1500;
_delay_ms(1500);
/* Reverse */
SERVO_L = 2000;
SERVO_R = 2000;
_delay_ms(1500);
/* Forwards */
SERVO_L = 1000;
SERVO_R = 1000;
_delay_ms(1500);
}
uint16_t read_adc(uint8_t channel)
{
ADMUX &= 0xF0;
ADMUX |= channel;
SET(ADCSRA, ADSC); // Start conversion
while (CHK(ADCSRA, ADSC)); // Wait for conversion to finish
return ADCW;
}
int main(void) int main(void)
{ {
uint16_t adc_val; init_leds();
init_servos();
init_led(); run_servos();
init_pwm(); read_temp();
init_adc();
while (1) {
adc_val = read_adc(0);
if (adc_val <= 512) {
SERVO_R = 2000;
SERVO_L = 2000;
} else {
SERVO_R = 1000;
SERVO_L = 1000;
}
}
return 0; return 0;
} }

View File

@ -10,59 +10,56 @@
*/ */
#include <avr/io.h> #include <avr/io.h>
#include "common.h"
#define set_bit(reg,bit) reg |= (1<<bit)
#define clr_bit(reg,bit) reg &= ~(1<<bit)
#define check_bit(reg,bit) (reg&(1<<bit))
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
void nrf24_setupPins() void nrf24_setupPins()
{ {
set_bit(DDRC, 0); // CE output SET(DDRC, 0); // CE output
set_bit(DDRC, 1); // CSN output SET(DDRC, 1); // CSN output
set_bit(DDRC, 2); // SCK output SET(DDRC, 2); // SCK output
set_bit(DDRC, 3); // MOSI output SET(DDRC, 3); // MOSI output
clr_bit(DDRC, 4); // MISO input CLR(DDRC, 4); // MISO input
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
void nrf24_ce_digitalWrite(uint8_t state) void nrf24_ce_digitalWrite(uint8_t state)
{ {
if (state) { if (state) {
set_bit(PORTC, 0); SET(PORTC, 0);
} else { } else {
clr_bit(PORTC, 0); CLR(PORTC, 0);
} }
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
void nrf24_csn_digitalWrite(uint8_t state) void nrf24_csn_digitalWrite(uint8_t state)
{ {
if (state) { if (state) {
set_bit(PORTC, 1); SET(PORTC, 1);
} else { } else {
clr_bit(PORTC, 1); CLR(PORTC, 1);
} }
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
void nrf24_sck_digitalWrite(uint8_t state) void nrf24_sck_digitalWrite(uint8_t state)
{ {
if (state) { if (state) {
set_bit(PORTC, 2); SET(PORTC, 2);
} else { } else {
clr_bit(PORTC, 2); CLR(PORTC, 2);
} }
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
void nrf24_mosi_digitalWrite(uint8_t state) void nrf24_mosi_digitalWrite(uint8_t state)
{ {
if (state) { if (state) {
set_bit(PORTC, 3); SET(PORTC, 3);
} else { } else {
clr_bit(PORTC, 3); CLR(PORTC, 3);
} }
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
uint8_t nrf24_miso_digitalRead() uint8_t nrf24_miso_digitalRead()
{ {
return check_bit(PINC, 4); return CHK(PINC, 4);
} }
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */

28
src/servos.c Normal file
View File

@ -0,0 +1,28 @@
#include <avr/io.h>
#include <util/delay.h>
#include "common.h"
#include "servos.h"
void init_servos(void)
{
SET(SERVO_DDR, SERVO_L_BIT);
SET(SERVO_DDR, SERVO_R_BIT);
SET(TCCR0A, COM0A1); // Clear OC0A on Compare Match, set OC0A at BOTTOM
SET(TCCR0A, COM0B1); // Clear OC0B on Compare Match, set OC0B at BOTTOM
// Fast PWM, 0xFF TOP
SET(TCCR0A, WGM00);
SET(TCCR0A, WGM01);
// Prescaler. clkPWM = clkIO / 64
SET(TCCR0B, CS00);
SET(TCCR0B, CS01);
}
void run_servos(void)
{
SERVO_L_REG = US2TIMER0(SERVO_MAX);
SERVO_R_REG = US2TIMER0(SERVO_MID);
_delay_ms(10000); // 10s
}

61
src/sonar.c Normal file
View File

@ -0,0 +1,61 @@
#include <avr/interrupt.h>
#include <util/delay.h>
#include "sonar.h"
volatile uint32_t overflow_counter = 0;
volatile uint32_t trig_counter = 0;
volatile uint32_t no_of_cycles = 0;
void init_sonar()
{
TRIG_OUTPUT_MODE();
ECHO_INPUT_MODE();
}
void trigger_sonar()
{
TRIG_LOW();
_delay_us(1);
TRIG_HIGH();
_delay_us(12);
TRIG_LOW();
_delay_us(1);
}
ISR(TIMER1_OVF_vect)
{
++overflow_counter;
TCNT1 = 0;
}
unsigned int read_sonar()
{
int dist_in_cm = 0;
init_sonar();
trigger_sonar();
// While echo pin is low
while (!(CHK(ECHO_PIN, ECHO_BIT))) {
if (++trig_counter > SONAR_TIMEOUT)
return TRIG_ERROR; // Received no response from echo
}
TCNT1 = 0;
TCCR1B |= (1 << CS10);
TIMSK1 |= (1 << TOIE1);
overflow_counter = 0;
sei();
// While echo pin is high
while (CHK(ECHO_PIN, ECHO_BIT)) {
if (((overflow_counter * TIMER_MAX) + TCNT1) > SONAR_TIMEOUT)
return ECHO_ERROR; // No echo within sonar range
}
TCCR1B = 0x00;
cli();
no_of_cycles = ((overflow_counter * TIMER_MAX) + TCNT1);
dist_in_cm = (no_of_cycles / (US_PER_CM * CYCLES_PER_US));
return dist_in_cm;
}

144
src/temperature.c Normal file
View File

@ -0,0 +1,144 @@
/*
ds18b20 lib 0x02
copyright (c) Davide Gironi, 2012
Released under GPLv3.
Please refer to LICENSE file for licensing information.
*/
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "common.h"
#include "temperature.h"
/*
* ds18b20 init
*/
uint8_t ds18b20_reset()
{
uint8_t i;
// low for 480us
CLR(DS18B20_PORT, DS18B20_BIT);
SET(DS18B20_DDR, DS18B20_BIT);
_delay_us(480);
// release line and wait for 60uS
CLR(DS18B20_DDR, DS18B20_BIT);
_delay_us(60);
// get value and wait 420us
i = CHK(DS18B20_PIN, DS18B20_BIT);
_delay_us(420);
// return the read value, 0=ok, 1=error
return i;
}
/*
* write one bit
*/
void ds18b20_writebit(uint8_t bit)
{
// low for 1uS
CLR(DS18B20_PORT, DS18B20_BIT);
SET(DS18B20_DDR, DS18B20_BIT);
_delay_us(1);
// if we want to write 1, release the line (if not will keep low)
if (bit)
CLR(DS18B20_DDR, DS18B20_BIT);
// wait 60uS and release the line
_delay_us(60);
DS18B20_DDR &= ~(1 << DS18B20_BIT);
}
/*
* read one bit
*/
uint8_t ds18b20_readbit(void)
{
uint8_t bit = 0;
// low for 1uS
CLR(DS18B20_PORT, DS18B20_BIT);
SET(DS18B20_DDR, DS18B20_BIT);
_delay_us(1);
// release line and wait for 14uS
CLR(DS18B20_DDR, DS18B20_BIT);
_delay_us(14);
// read the value
if (CHK(DS18B20_PIN, DS18B20_BIT))
bit = 1;
// wait 45uS and return read value
_delay_us(45);
return bit;
}
/*
* write one byte
*/
void ds18b20_writebyte(uint8_t byte)
{
uint8_t i = 8;
while (i--) {
ds18b20_writebit(byte & 1);
byte >>= 1;
}
}
/*
* read one byte
*/
uint8_t ds18b20_readbyte(void)
{
uint8_t i = 8, n = 0;
while (i--) {
n >>= 1;
n |= (ds18b20_readbit() << 7);
}
return n;
}
/*
* get temperature
*/
double ds18b20_gettemp()
{
uint8_t temperature_l;
uint8_t temperature_h;
double retd = 0;
#if DS18B20_STOPINTERRUPTONREAD == 1
cli();
#endif
ds18b20_reset(); // reset
ds18b20_writebyte(DS18B20_CMD_SKIPROM); // skip ROM
ds18b20_writebyte(DS18B20_CMD_CONVERTTEMP); // start temperature conversion
while (!ds18b20_readbit()); // wait until conversion is complete
ds18b20_reset(); // reset
ds18b20_writebyte(DS18B20_CMD_SKIPROM); // skip ROM
ds18b20_writebyte(DS18B20_CMD_RSCRATCHPAD); // read scratchpad
// read 2 byte from scratchpad
temperature_l = ds18b20_readbyte();
temperature_h = ds18b20_readbyte();
#if DS18B20_STOPINTERRUPTONREAD == 1
sei();
#endif
// convert the 12 bit value obtained
retd = ((temperature_h << 8) + temperature_l) * 0.0625;
return retd;
}