Revision 92
BRANCH autonomous_recharging branch created
branches/autonomous_recharging/code/projects/autonomous_recharging/archs/USI_TWI_Master.c | ||
---|---|---|
1 |
/***************************************************************************** |
|
2 |
* |
|
3 |
* Atmel Corporation |
|
4 |
* |
|
5 |
* File : USI_TWI_Master.c |
|
6 |
* Compiler : IAR EWAAVR 2.28a/3.10a |
|
7 |
* Revision : $Revision: 1.11 $ |
|
8 |
* Date : $Date: Tuesday, September 13, 2005 09:09:36 UTC $ |
|
9 |
* Updated by : $Author: jtyssoe $ |
|
10 |
* |
|
11 |
* Support mail : avr@atmel.com |
|
12 |
* |
|
13 |
* Supported devices : All device with USI module can be used. |
|
14 |
* The example is written for the ATmega169, ATtiny26 and ATtiny2313 |
|
15 |
* |
|
16 |
* AppNote : AVR310 - Using the USI module as a TWI Master |
|
17 |
* |
|
18 |
* Description : This is an implementation of an TWI master using |
|
19 |
* the USI module as basis. The implementation assumes the AVR to |
|
20 |
* be the only TWI master in the system and can therefore not be |
|
21 |
* used in a multi-master system. |
|
22 |
* Usage : Initialize the USI module by calling the USI_TWI_Master_Initialise() |
|
23 |
* function. Hence messages/data are transceived on the bus using |
|
24 |
* the USI_TWI_Transceive() function. The transceive function |
|
25 |
* returns a status byte, which can be used to evaluate the |
|
26 |
* success of the transmission. |
|
27 |
* |
|
28 |
****************************************************************************/ |
|
29 |
#ifndef _USI_TWI_MASTER_H |
|
30 |
#define _USI_TWI_MASTER_H |
|
31 |
|
|
32 |
#include <util/delay.h> |
|
33 |
#include <avr/io.h> |
|
34 |
#include <avr/interrupt.h> |
|
35 |
#include "USI_TWI_Master.h" |
|
36 |
|
|
37 |
unsigned char USI_TWI_Master_Transfer( unsigned char ); |
|
38 |
unsigned char USI_TWI_Master_Stop( void ); |
|
39 |
|
|
40 |
union USI_TWI_state |
|
41 |
{ |
|
42 |
unsigned char errorState; // Can reuse the TWI_state for error states due to that it will not be need if there exists an error. |
|
43 |
struct |
|
44 |
{ |
|
45 |
unsigned char addressMode : 1; |
|
46 |
unsigned char masterWriteDataMode : 1; |
|
47 |
unsigned char unused : 6; |
|
48 |
}; |
|
49 |
} USI_TWI_state; |
|
50 |
|
|
51 |
/*--------------------------------------------------------------- |
|
52 |
USI TWI single master initialization function |
|
53 |
---------------------------------------------------------------*/ |
|
54 |
void USI_TWI_Master_Initialise( void ) |
|
55 |
{ |
|
56 |
PORT_USI |= (1<<PIN_USI_SDA); // Enable pullup on SDA, to set high as released state. |
|
57 |
PORT_USI |= (1<<PIN_USI_SCL); // Enable pullup on SCL, to set high as released state. |
|
58 |
|
|
59 |
DDR_USI |= (1<<PIN_USI_SCL); // Enable SCL as output. |
|
60 |
DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output. |
|
61 |
|
|
62 |
USIDR = 0xFF; // Preload dataregister with "released level" data. |
|
63 |
USICR = (0<<USISIE)|(0<<USIOIE)| // Disable Interrupts. |
|
64 |
(1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode. |
|
65 |
(1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software stobe as counter clock source |
|
66 |
(0<<USITC); |
|
67 |
USISR = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags, |
|
68 |
(0x0<<USICNT0); // and reset counter. |
|
69 |
} |
|
70 |
|
|
71 |
/*--------------------------------------------------------------- |
|
72 |
Use this function to get hold of the error message from the last transmission |
|
73 |
---------------------------------------------------------------*/ |
|
74 |
unsigned char USI_TWI_Get_State_Info( void ) |
|
75 |
{ |
|
76 |
return ( USI_TWI_state.errorState ); // Return error state. |
|
77 |
} |
|
78 |
|
|
79 |
/*--------------------------------------------------------------- |
|
80 |
USI Transmit and receive function. LSB of first byte in data |
|
81 |
indicates if a read or write cycles is performed. If set a read |
|
82 |
operation is performed. |
|
83 |
|
|
84 |
Function generates (Repeated) Start Condition, sends address and |
|
85 |
R/W, Reads/Writes Data, and verifies/sends ACK. |
|
86 |
|
|
87 |
Success or error code is returned. Error codes are defined in |
|
88 |
USI_TWI_Master.h |
|
89 |
---------------------------------------------------------------*/ |
|
90 |
unsigned char USI_TWI_Start_Transceiver_With_Data( unsigned char *msg, unsigned char msgSize) |
|
91 |
{ |
|
92 |
unsigned char tempUSISR_8bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and |
|
93 |
(0x0<<USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges. |
|
94 |
unsigned char tempUSISR_1bit = (1<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Prepare register value to: Clear flags, and |
|
95 |
(0xE<<USICNT0); // set USI to shift 1 bit i.e. count 2 clock edges. |
|
96 |
|
|
97 |
USI_TWI_state.errorState = 0; |
|
98 |
USI_TWI_state.addressMode = TRUE; |
|
99 |
|
|
100 |
|
|
101 |
|
|
102 |
if ( !(*msg & (1<<TWI_READ_BIT)) ) // The LSB in the address byte determines if is a masterRead or masterWrite operation. |
|
103 |
{ |
|
104 |
USI_TWI_state.masterWriteDataMode = TRUE; |
|
105 |
} |
|
106 |
|
|
107 |
/* Release SCL to ensure that (repeated) Start can be performed */ |
|
108 |
PORT_USI |= (1<<PIN_USI_SCL); // Release SCL. |
|
109 |
while( !(PORT_USI & (1<<PIN_USI_SCL)) ); // Verify that SCL becomes high. |
|
110 |
|
|
111 |
_delay_loop_1(T2_TWI); |
|
112 |
//_delay_us(T4_TWI); |
|
113 |
//__delay_cycles( T2_TWI ); // Delay for T2TWI if TWI_STANDARD_MODE |
|
114 |
|
|
115 |
|
|
116 |
/* Generate Start Condition */ |
|
117 |
PORT_USI &= ~(1<<PIN_USI_SDA); // Force SDA LOW. |
|
118 |
_delay_loop_1(T4_TWI); |
|
119 |
//_delay_us(T4_TWI); |
|
120 |
//__delay_cycles( T4_TWI ); |
|
121 |
PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW. |
|
122 |
PORT_USI |= (1<<PIN_USI_SDA); // Release SDA. |
|
123 |
|
|
124 |
//Start |
|
125 |
PORTA |= _BV(PA3); |
|
126 |
|
|
127 |
|
|
128 |
/*Write address and Read/Write data */ |
|
129 |
do |
|
130 |
{ |
|
131 |
/* If masterWrite cycle (or inital address tranmission)*/ |
|
132 |
if (USI_TWI_state.addressMode || USI_TWI_state.masterWriteDataMode) |
|
133 |
{ |
|
134 |
PORTA |= _BV(PA4); |
|
135 |
/* Write a byte */ |
|
136 |
PORT_USI &= ~(1<<PIN_USI_SCL); // Pull SCL LOW. |
|
137 |
USIDR = *(msg++); // Setup data. |
|
138 |
USI_TWI_Master_Transfer( tempUSISR_8bit ); // Send 8 bits on bus. |
|
139 |
|
|
140 |
/* Clock and verify (N)ACK from slave */ |
|
141 |
DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input. |
|
142 |
|
|
143 |
PORTA |= _BV(PA5); |
|
144 |
|
|
145 |
if( USI_TWI_Master_Transfer( tempUSISR_1bit ) & (1<<TWI_NACK_BIT) ) |
|
146 |
{ |
|
147 |
//Shit |
|
148 |
PORTA |= _BV(PA3) | _BV(PA4) | _BV(PA5) | _BV(PA6) | _BV(PA7); |
|
149 |
|
|
150 |
if ( USI_TWI_state.addressMode ) |
|
151 |
USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS; |
|
152 |
else |
|
153 |
USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA; |
|
154 |
return (FALSE); |
|
155 |
} |
|
156 |
USI_TWI_state.addressMode = FALSE; // Only perform address transmission once. |
|
157 |
|
|
158 |
|
|
159 |
PORTA &= (~_BV(PA4) | ~_BV(PA5)); |
|
160 |
} |
|
161 |
/* Else masterRead cycle*/ |
|
162 |
else |
|
163 |
{ |
|
164 |
/* Read a data byte */ |
|
165 |
DDR_USI &= ~(1<<PIN_USI_SDA); // Enable SDA as input. |
|
166 |
*(msg++) = USI_TWI_Master_Transfer( tempUSISR_8bit ); |
|
167 |
|
|
168 |
/* Prepare to generate ACK (or NACK in case of End Of Transmission) */ |
|
169 |
if( msgSize == 1) // If transmission of last byte was performed. |
|
170 |
{ |
|
171 |
USIDR = 0xFF; // Load NACK to confirm End Of Transmission. |
|
172 |
} |
|
173 |
else |
|
174 |
{ |
|
175 |
USIDR = 0x00; // Load ACK. Set data register bit 7 (output for SDA) low. |
|
176 |
} |
|
177 |
USI_TWI_Master_Transfer( tempUSISR_1bit ); // Generate ACK/NACK. |
|
178 |
} |
|
179 |
}while( --msgSize) ; // Until all data sent/received. |
|
180 |
|
|
181 |
|
|
182 |
PORTA |= _BV(PA6); |
|
183 |
|
|
184 |
USI_TWI_Master_Stop(); // Send a STOP condition on the TWI bus. |
|
185 |
|
|
186 |
/* Transmission successfully completed*/ |
|
187 |
return (TRUE); |
|
188 |
} |
|
189 |
|
|
190 |
/*--------------------------------------------------------------- |
|
191 |
Core function for shifting data in and out from the USI. |
|
192 |
Data to be sent has to be placed into the USIDR prior to calling |
|
193 |
this function. Data read, will be return'ed from the function. |
|
194 |
---------------------------------------------------------------*/ |
|
195 |
unsigned char USI_TWI_Master_Transfer( unsigned char temp ) |
|
196 |
{ |
|
197 |
USISR = temp; // Set USISR according to temp. |
|
198 |
// Prepare clocking. |
|
199 |
temp = (0<<USISIE)|(0<<USIOIE)| // Interrupts disabled |
|
200 |
(1<<USIWM1)|(0<<USIWM0)| // Set USI in Two-wire mode. |
|
201 |
(1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software clock strobe as source. |
|
202 |
(1<<USITC); // Toggle Clock Port. |
|
203 |
do |
|
204 |
{ |
|
205 |
//__delay_cycles( T2_TWI ); |
|
206 |
_delay_loop_1(T2_TWI); |
|
207 |
//_delay_us(T2_TWI); |
|
208 |
USICR = temp; // Generate positve SCL edge. |
|
209 |
while( !(PIN_USI & (1<<PIN_USI_SCL)) );// Wait for SCL to go high. |
|
210 |
_delay_loop_1(T4_TWI); |
|
211 |
//__delay_cycles( T4_TWI ); |
|
212 |
// _delay_us(T4_TWI); |
|
213 |
USICR = temp; // Generate negative SCL edge. |
|
214 |
}while( !(USISR & (1<<USIOIF)) ); // Check for transfer complete. |
|
215 |
_delay_loop_1(T2_TWI); |
|
216 |
//_delay_us(T2_TWI); |
|
217 |
//__delay_cycles( T2_TWI ); |
|
218 |
temp = USIDR; // Read out data. |
|
219 |
USIDR = 0xFF; // Release SDA. |
|
220 |
DDR_USI |= (1<<PIN_USI_SDA); // Enable SDA as output. |
|
221 |
|
|
222 |
return temp; // Return the data from the USIDR |
|
223 |
} |
|
224 |
|
|
225 |
/*--------------------------------------------------------------- |
|
226 |
Function for generating a TWI Stop Condition. Used to release |
|
227 |
the TWI bus. |
|
228 |
---------------------------------------------------------------*/ |
|
229 |
unsigned char USI_TWI_Master_Stop( void ) |
|
230 |
{ |
|
231 |
PORT_USI &= ~(1<<PIN_USI_SDA); // Pull SDA low. |
|
232 |
PORT_USI |= (1<<PIN_USI_SCL); // Release SCL. |
|
233 |
while( !(PIN_USI & (1<<PIN_USI_SCL)) ); // Wait for SCL to go high. |
|
234 |
_delay_loop_1(T4_TWI); |
|
235 |
//_delay_us(T4_TWI); |
|
236 |
//__delay_cycles( T4_TWI ); |
|
237 |
PORT_USI |= (1<<PIN_USI_SDA); // Release SDA. |
|
238 |
_delay_loop_1(T2_TWI); |
|
239 |
//_delay_us(T2_TWI); |
|
240 |
//__delay_cycles( T2_TWI ); |
|
241 |
|
|
242 |
#ifdef SIGNAL_VERIFY |
|
243 |
if( !(USISR & (1<<USIPF)) ) |
|
244 |
{ |
|
245 |
USI_TWI_state.errorState = USI_TWI_MISSING_STOP_CON; |
|
246 |
return (FALSE); |
|
247 |
} |
|
248 |
#endif |
|
249 |
|
|
250 |
return (TRUE); |
|
251 |
} |
|
252 |
|
|
253 |
#endif |
branches/autonomous_recharging/code/projects/autonomous_recharging/archs/Charging.c | ||
---|---|---|
1 |
#include <avr/io.h> |
|
2 |
#include <avr/interrupt.h> |
|
3 |
#include <avr/sleep.h> |
|
4 |
#include "i2c.h" |
|
5 |
|
|
6 |
#define TRICKLE |
|
7 |
|
|
8 |
|
|
9 |
//These are in ADC steps; if any values change in the charging |
|
10 |
//circuitry these will have to be recalculated |
|
11 |
#ifndef TRICKLE |
|
12 |
#define FAST_I 450//660 //660 fries the 5A fuse!! |
|
13 |
#else |
|
14 |
#define FAST_I 20 //Works => 1.3A |
|
15 |
#endif |
|
16 |
|
|
17 |
#define TEST_CURR 550 |
|
18 |
|
|
19 |
#define MAX_V 1020//990 //7.75V |
|
20 |
|
|
21 |
|
|
22 |
#define MAX_T 300 |
|
23 |
#define MIN_T 730 |
|
24 |
//range is 0 to 45 C |
|
25 |
//cal tests: |
|
26 |
//room temp - 25 |
|
27 |
//value ~500, varies from battery to battery, but is consistent on one battery |
|
28 |
//freezer 737 |
|
29 |
//heat gun at a distance 461 |
|
30 |
|
|
31 |
//change in one minute |
|
32 |
#define MAX_DT 30 |
|
33 |
#define MAX_DV 30 |
|
34 |
|
|
35 |
|
|
36 |
//The following times are in seconds |
|
37 |
#define MAX_FAST_TIME 5400 |
|
38 |
#define MAX_TRICKLE_TIME 600 |
|
39 |
|
|
40 |
//debug pins |
|
41 |
#define debug_time PA3 |
|
42 |
#define debug_curr PA4 |
|
43 |
#define debug_volt PA5 |
|
44 |
#define debug_temp PA6 |
|
45 |
#define debug_12in PA7 |
|
46 |
|
|
47 |
//be sure admux also sets the MUX5 bit which is in ADCSRB |
|
48 |
#define ADMUX_I |
|
49 |
#define ADMUX_V |
|
50 |
#define ADMUX_T |
|
51 |
|
|
52 |
#define ROBOT_TX PB1 |
|
53 |
#define ROBOT_RX PB2 |
|
54 |
#define PWM PB3 |
|
55 |
#define DETECT_12V PB6 |
|
56 |
|
|
57 |
#define LED1 PB4 //Green |
|
58 |
#define LED2 PB5 //Red |
|
59 |
|
|
60 |
|
|
61 |
//LED States: |
|
62 |
//Red - Fast Charging |
|
63 |
//Green - Trickle Charging |
|
64 |
//Both steady - done charging |
|
65 |
//Both Blinking - Error |
|
66 |
|
|
67 |
#define INT_COUNT 2 //interrupts per second |
|
68 |
#define AVG_COUNT 64 //number of times to count current |
|
69 |
|
|
70 |
//To enable the PWM write : TCCR1B = (_Bv(CS10));//enable PWM |
|
71 |
|
|
72 |
uint8_t interrupt_count = INT_COUNT; |
|
73 |
|
|
74 |
volatile uint32_t abs_time=1; // start at one second so it doesnt do the minute checks right away |
|
75 |
volatile uint8_t new_second=0; //only used as a boolean |
|
76 |
|
|
77 |
volatile uint8_t error=0; |
|
78 |
volatile uint8_t status; |
|
79 |
|
|
80 |
volatile uint8_t steady_current = 0; |
|
81 |
|
|
82 |
//DT must be triggered twice in a row |
|
83 |
volatile uint8_t last_DT = 0; |
|
84 |
//same for DV |
|
85 |
volatile uint8_t last_DV = 0; |
|
86 |
|
|
87 |
#define FAST_CHARGE 1 |
|
88 |
#define TRICKLE_CHARGE 2 |
|
89 |
|
|
90 |
|
|
91 |
|
|
92 |
void wait(int ops) |
|
93 |
{ |
|
94 |
int i = 0; |
|
95 |
while(i<ops) |
|
96 |
i++; |
|
97 |
} |
|
98 |
|
|
99 |
|
|
100 |
|
|
101 |
int avg_ADC(void) |
|
102 |
{ |
|
103 |
int av; |
|
104 |
char i; |
|
105 |
|
|
106 |
//Calculate a average out of the next 8 A/D conversions |
|
107 |
for(av=0,i=8;i;--i) |
|
108 |
{ |
|
109 |
ADCSRA |= _BV(ADSC); // start new A/D conversion |
|
110 |
while (!(ADCSRA & (_BV(ADIF)))) // wait until ADC is ready |
|
111 |
; |
|
112 |
av = av+ADC; |
|
113 |
} |
|
114 |
av = av/8; |
|
115 |
|
|
116 |
//ADCSRA &= ~_BV(ADEN); |
|
117 |
|
|
118 |
return av; |
|
119 |
|
|
120 |
} |
|
121 |
|
|
122 |
int get_voltage(void) |
|
123 |
{ |
|
124 |
ADMUX = _BV(MUX0); |
|
125 |
|
|
126 |
ADCSRB &= ~_BV(MUX5); |
|
127 |
|
|
128 |
return avg_ADC(); |
|
129 |
} |
|
130 |
|
|
131 |
int get_current(void) |
|
132 |
{ |
|
133 |
ADMUX = _BV(MUX1); |
|
134 |
|
|
135 |
ADCSRB |= _BV(MUX5); |
|
136 |
|
|
137 |
return avg_ADC(); |
|
138 |
} |
|
139 |
|
|
140 |
int get_temperature(void) |
|
141 |
{ |
|
142 |
ADMUX = _BV(MUX1); |
|
143 |
|
|
144 |
ADCSRB &= ~_BV(MUX5); |
|
145 |
|
|
146 |
return avg_ADC(); |
|
147 |
} |
|
148 |
|
|
149 |
int get_avg_voltage(void) |
|
150 |
{ |
|
151 |
int count=0; |
|
152 |
uint32_t sum=0; |
|
153 |
|
|
154 |
//OCR1B =120; |
|
155 |
while(count < AVG_COUNT) |
|
156 |
{ |
|
157 |
sum += get_voltage(); |
|
158 |
count++; |
|
159 |
} |
|
160 |
|
|
161 |
return sum/AVG_COUNT; |
|
162 |
} |
|
163 |
|
|
164 |
int get_avg_current(void) |
|
165 |
{ |
|
166 |
int count=0; |
|
167 |
uint32_t sum=0; |
|
168 |
|
|
169 |
//OCR1B =120; |
|
170 |
while(count < AVG_COUNT) |
|
171 |
{ |
|
172 |
sum += get_current(); |
|
173 |
count++; |
|
174 |
} |
|
175 |
|
|
176 |
return sum/AVG_COUNT; |
|
177 |
} |
|
178 |
|
|
179 |
int get_avg_temperature(void) |
|
180 |
{ |
|
181 |
int count=0; |
|
182 |
uint32_t sum=0; |
|
183 |
|
|
184 |
//OCR1B =120; |
|
185 |
while(count < AVG_COUNT) |
|
186 |
{ |
|
187 |
sum += get_temperature(); |
|
188 |
count++; |
|
189 |
} |
|
190 |
|
|
191 |
return sum/AVG_COUNT; |
|
192 |
} |
|
193 |
|
|
194 |
|
|
195 |
uint8_t supply_voltage(void) |
|
196 |
{ |
|
197 |
return PINB & _BV(DETECT_12V); |
|
198 |
} |
|
199 |
|
|
200 |
void clear_err(void) |
|
201 |
{ |
|
202 |
error=0; |
|
203 |
PORTB &= ~(_BV(LED1)|_BV(LED2)); |
|
204 |
|
|
205 |
if(status==FAST_CHARGE) |
|
206 |
PORTB |= _BV(LED2); |
|
207 |
|
|
208 |
if(status==TRICKLE_CHARGE) |
|
209 |
PORTB |= _BV(LED1); |
|
210 |
} |
|
211 |
|
|
212 |
void wait_8th(void) |
|
213 |
{ |
|
214 |
uint8_t start = abs_time % 8; |
|
215 |
|
|
216 |
while(abs_time % 8 == start) |
|
217 |
{ |
|
218 |
/*if(supply_voltage()) |
|
219 |
PORTB |= _BV(LED1); |
|
220 |
else |
|
221 |
PORTB &= ~_BV(LED1); |
|
222 |
if(get_voltage()>100) |
|
223 |
PORTB |= _BV(LED2); |
|
224 |
else |
|
225 |
PORTB &= ~_BV(LED2);*/ |
|
226 |
} |
|
227 |
} |
|
228 |
|
|
229 |
void send_err(void) |
|
230 |
{ |
|
231 |
OCR1B=0;//turn off the PWM to be safe |
|
232 |
|
|
233 |
PORTB &= ~(_BV(LED1)|_BV(LED2)); |
|
234 |
if(status!=0)//leave last error if there was one |
|
235 |
PORTA &= ~(_BV(debug_time)|_BV(debug_curr)|_BV(debug_volt)|_BV(debug_temp)|_BV(debug_12in)); |
|
236 |
error=1; |
|
237 |
status=0; |
|
238 |
} |
|
239 |
|
|
240 |
void send_done(void) |
|
241 |
{ |
|
242 |
char tempData; |
|
243 |
//Finished, leave |
|
244 |
tempData = 'F'; |
|
245 |
i2c_putpacket(0x01, &tempData, 1); |
|
246 |
|
|
247 |
PORTA &= ~(_BV(debug_time)|_BV(debug_curr)|_BV(debug_volt)|_BV(debug_temp)|_BV(debug_12in)); |
|
248 |
|
|
249 |
} |
|
250 |
|
|
251 |
void setup(void) |
|
252 |
{ |
|
253 |
DDRA = (_BV(debug_time)|_BV(debug_curr)|_BV(debug_volt)|_BV(debug_temp)|_BV(debug_12in)); |
|
254 |
PORTA = 0x00; |
|
255 |
DDRB = (_BV(ROBOT_TX)|_BV(PWM)|_BV(LED1)|_BV(LED2)); //confiure output pins |
|
256 |
PORTB = 0x00; |
|
257 |
|
|
258 |
ADCSRA = (_BV(ADEN)|_BV(ADPS2)|_BV(ADPS1)); //start ADC with a division factor of 64 |
|
259 |
|
|
260 |
TCCR0B = (_BV(CS01)); //set timer 0 for realtime mode |
|
261 |
TCCR0A = (_BV(TCW0)); |
|
262 |
TIMSK = (_BV(TOIE0)); //enable overflow interrupts |
|
263 |
|
|
264 |
TCCR1A = (_BV(COM1B1)|_BV(PWM1B)|_BV(COM1A1)|_BV(PWM1A)); //clear timer 1 on compare, set at 0x00. Fast PWM mode |
|
265 |
TCCR1B |= _BV(CS12)|_BV(CS10); //leave timer on and set compare to 0 to make output off |
|
266 |
OCR1B = 0; |
|
267 |
OCR1A = 0; |
|
268 |
|
|
269 |
sei(); |
|
270 |
} |
|
271 |
|
|
272 |
int regulate_current(int i) |
|
273 |
{ |
|
274 |
if(status==0) |
|
275 |
{ |
|
276 |
OCR1B = 0; |
|
277 |
return 0; |
|
278 |
} |
|
279 |
|
|
280 |
PORTA ^= _BV(debug_curr); |
|
281 |
|
|
282 |
int curr=0; |
|
283 |
int count=0; |
|
284 |
int diff=0; |
|
285 |
uint32_t sum=0; |
|
286 |
|
|
287 |
//OCR1B =120; |
|
288 |
while(count < AVG_COUNT) |
|
289 |
{ |
|
290 |
sum += get_current(); |
|
291 |
count++; |
|
292 |
} |
|
293 |
|
|
294 |
curr = sum/AVG_COUNT; |
|
295 |
//OCR1A = curr >> 2; |
|
296 |
|
|
297 |
|
|
298 |
//old linear regulation |
|
299 |
/* |
|
300 |
if(OCR1B <255 && curr < i) |
|
301 |
OCR1B++; |
|
302 |
else if(OCR1B >0 && curr > i) |
|
303 |
OCR1B--; |
|
304 |
|
|
305 |
return curr; |
|
306 |
*/ |
|
307 |
|
|
308 |
|
|
309 |
//cool control law stuff |
|
310 |
diff=curr-i; |
|
311 |
|
|
312 |
OCR1B = diff/4 + curr/4; //K*Ierr + Kguess |
|
313 |
|
|
314 |
|
|
315 |
|
|
316 |
//1024/255 |
|
317 |
/*if(OCR1B <255 && curr<i) |
|
318 |
OCR1B += (i-curr)/4; |
|
319 |
else if(OCR1B >0 && curr > i) |
|
320 |
OCR1B -= (curr-i)/4;*/ |
|
321 |
//differential regulation (sort of) |
|
322 |
/*diff = i-curr; |
|
323 |
|
|
324 |
if(diff<8) |
|
325 |
steady_current=1; |
|
326 |
else |
|
327 |
steady_current=0; |
|
328 |
|
|
329 |
OCR1B += diff/4;*/ |
|
330 |
|
|
331 |
} |
|
332 |
|
|
333 |
void check_voltage(void) |
|
334 |
{ |
|
335 |
int volt = get_avg_voltage(); |
|
336 |
|
|
337 |
|
|
338 |
if(volt > MAX_V) |
|
339 |
{ |
|
340 |
OCR1A = 128; |
|
341 |
send_err(); |
|
342 |
PORTA |= _BV(debug_volt); |
|
343 |
status = 0; |
|
344 |
} |
|
345 |
} |
|
346 |
|
|
347 |
void check_temperature(void) |
|
348 |
{ |
|
349 |
int temp = get_avg_temperature(); |
|
350 |
|
|
351 |
//temp readings are reversed |
|
352 |
if(temp < MAX_T || temp > MIN_T) |
|
353 |
{ |
|
354 |
OCR1A = 192; |
|
355 |
send_err(); |
|
356 |
PORTA |= _BV(debug_temp); |
|
357 |
status=0; |
|
358 |
} |
|
359 |
} |
|
360 |
|
|
361 |
|
|
362 |
//takes a 7-bit ionteger and displays it on the 7 LEDs with the Green being the MSB |
|
363 |
void LED_out(int i) |
|
364 |
{ |
|
365 |
if(i & 64) |
|
366 |
PORTB |= _BV(LED1); |
|
367 |
else |
|
368 |
PORTB &= ~_BV(LED1); |
|
369 |
|
|
370 |
if(i & 32) |
|
371 |
PORTB |= _BV(LED2); |
|
372 |
else |
|
373 |
PORTB &= ~_BV(LED2); |
|
374 |
|
|
375 |
if(i & 16) |
|
376 |
PORTA |= _BV(PA3); |
|
377 |
else |
|
378 |
PORTA &= ~_BV(PA3); |
|
379 |
|
|
380 |
if(i & 8) |
|
381 |
PORTA |= _BV(PA4); |
|
382 |
else |
|
383 |
PORTA &= ~_BV(PA4); |
|
384 |
|
|
385 |
if(i & 4) |
|
386 |
PORTA |= _BV(PA5); |
|
387 |
else |
|
388 |
PORTA &= ~_BV(PA5); |
|
389 |
|
|
390 |
if(i & 2) |
|
391 |
PORTA |= _BV(PA6); |
|
392 |
else |
|
393 |
PORTA &= ~_BV(PA6); |
|
394 |
|
|
395 |
if(i & 1) |
|
396 |
PORTA |= _BV(PA7); |
|
397 |
else |
|
398 |
PORTA &= ~_BV(PA7); |
|
399 |
} |
|
400 |
|
|
401 |
|
|
402 |
void test_board(void) |
|
403 |
{ |
|
404 |
setup(); |
|
405 |
abs_time = 0; |
|
406 |
status = 1; |
|
407 |
char tempData[5]; |
|
408 |
i2c_init(); |
|
409 |
int volt; |
|
410 |
int temp; |
|
411 |
int curr; |
|
412 |
int meas_count; |
|
413 |
int mod=0; |
|
414 |
sei(); |
|
415 |
OCR1B = 0; |
|
416 |
while(1) |
|
417 |
{ |
|
418 |
mod=abs_time%4; |
|
419 |
while(abs_time%4==mod); |
|
420 |
|
|
421 |
/*if((abs_time>>3)%3==0) |
|
422 |
OCR1B=21; |
|
423 |
else if((abs_time>>3)%3==1) |
|
424 |
OCR1B=57; |
|
425 |
else |
|
426 |
OCR1B=85;*/ |
|
427 |
|
|
428 |
tempData[0] = 'C'; |
|
429 |
tempData[1] = abs_time>>8; |
|
430 |
tempData[2] = abs_time&0xFF; |
|
431 |
i2c_putpacket(0x01, tempData, 3); |
|
432 |
|
|
433 |
mod=abs_time%4; |
|
434 |
while(abs_time%4==mod) |
|
435 |
{ |
|
436 |
if(supply_voltage()) |
|
437 |
{ |
|
438 |
//curr = regulate_current(500); |
|
439 |
curr = get_avg_current(); |
|
440 |
OCR1B = 100; |
|
441 |
} |
|
442 |
else |
|
443 |
{ |
|
444 |
curr = 0; |
|
445 |
OCR1B = 0; |
|
446 |
} |
|
447 |
} |
|
448 |
|
|
449 |
|
|
450 |
tempData[0] = 'P'; |
|
451 |
tempData[1] = 0; |
|
452 |
tempData[2] = OCR1B; |
|
453 |
i2c_putpacket(0x01, tempData, 3); |
|
454 |
tempData[0] = 'I'; |
|
455 |
tempData[1] = curr>>8; |
|
456 |
tempData[2] = curr&0xFF; |
|
457 |
i2c_putpacket(0x01, tempData, 3); |
|
458 |
curr=6666; |
|
459 |
|
|
460 |
mod=abs_time%4; |
|
461 |
while(abs_time%4==mod) |
|
462 |
{ |
|
463 |
volt = get_avg_voltage(); |
|
464 |
} |
|
465 |
|
|
466 |
tempData[0] = 'V'; |
|
467 |
tempData[1] = volt>>8; |
|
468 |
tempData[2] = volt&0xFF; |
|
469 |
i2c_putpacket(0x01, tempData, 3); |
|
470 |
|
|
471 |
volt=6666; |
|
472 |
|
|
473 |
mod=abs_time%4; |
|
474 |
while(abs_time%4==mod) |
|
475 |
{ |
|
476 |
temp = get_avg_temperature(); |
|
477 |
|
|
478 |
} |
|
479 |
|
|
480 |
tempData[0] = 'T'; |
|
481 |
tempData[1] = temp>>8; |
|
482 |
tempData[2] = temp&0xFF; |
|
483 |
i2c_putpacket(0x01, tempData, 3); |
|
484 |
|
|
485 |
temp=6666; |
|
486 |
} |
|
487 |
int c=0,oc; |
|
488 |
oc=get_avg_temperature(); |
|
489 |
//this will read the temperature and output it to the LEDS. |
|
490 |
//to read the value, enter the LEDs as binary, with the bottom green as the MSB. |
|
491 |
//after two second the LEDS will toggle to the next 7 bits |
|
492 |
/*while(1) |
|
493 |
{ |
|
494 |
c=oc-get_avg_temperature(); |
|
495 |
oc+=c; |
|
496 |
|
|
497 |
if(c<0) |
|
498 |
c=-c; |
|
499 |
|
|
500 |
if(c<5) |
|
501 |
break; |
|
502 |
}*/ |
|
503 |
/* |
|
504 |
while(1) |
|
505 |
{ |
|
506 |
LED_out(oc>>7); |
|
507 |
for(c=0;c<16;c++) |
|
508 |
wait_8th(); |
|
509 |
LED_out(oc); |
|
510 |
for(c=0;c<16;c++) |
|
511 |
wait_8th(); |
|
512 |
}*/ |
|
513 |
|
|
514 |
|
|
515 |
/*PORTB |= (_BV(LED1)|_BV(LED2)); |
|
516 |
|
|
517 |
while(1) |
|
518 |
{ |
|
519 |
PORTA ^= _BV(debug_time); |
|
520 |
wait_8th(); |
|
521 |
c=get_current()-FAST_I; |
|
522 |
if(c<0) |
|
523 |
c=-c; |
|
524 |
if(c<4) |
|
525 |
PORTA |= _BV(debug_curr); |
|
526 |
else |
|
527 |
PORTA &= ~_BV(debug_curr); |
|
528 |
wait_8th(); |
|
529 |
if(get_avg_voltage() > 50) |
|
530 |
PORTA |= _BV(debug_volt); |
|
531 |
else |
|
532 |
PORTA &= ~_BV(debug_volt); |
|
533 |
wait_8th(); |
|
534 |
if(get_avg_temperature() > MAX_T) |
|
535 |
PORTA |= _BV(debug_temp); |
|
536 |
else |
|
537 |
PORTA &= ~_BV(debug_temp); |
|
538 |
wait_8th(); |
|
539 |
if(supply_voltage()) |
|
540 |
PORTA |= _BV(debug_12in); |
|
541 |
else |
|
542 |
PORTA &= ~_BV(debug_12in); |
|
543 |
wait_8th(); |
|
544 |
}*/ |
|
545 |
|
|
546 |
} |
|
547 |
|
|
548 |
|
|
549 |
int main(void) |
|
550 |
{ |
|
551 |
test_board(); |
|
552 |
new_second=0; |
|
553 |
char tempData[5]; //For i2c communication |
|
554 |
//test_board(); |
|
555 |
char noVoltagePrintFlag = 0; |
|
556 |
|
|
557 |
setup(); |
|
558 |
i2c_init(); |
|
559 |
|
|
560 |
/*GIMSK = (_BV(PCIE0)); //enable PCINT interrupts |
|
561 |
PCMSK1 = (_BV(PCINT10)); //enable pin change interrupt on ROBOT_RX |
|
562 |
MCUCR = (_BV(SE)|_BV(SM1));// (power-down mode) |
|
563 |
*/ |
|
564 |
|
|
565 |
OCR1B=0; |
|
566 |
|
|
567 |
sei(); |
|
568 |
|
|
569 |
tempData[0] = 'S'; |
|
570 |
tempData[1] = 'S'; |
|
571 |
tempData[2] = 'S'; |
|
572 |
tempData[3] = 'S'; |
|
573 |
tempData[4] = 'S'; |
|
574 |
i2c_putpacket(0x01, tempData, 5); |
|
575 |
|
|
576 |
int temp=0; |
|
577 |
int last_temp = get_avg_temperature(); |
|
578 |
|
|
579 |
int volt=0; |
|
580 |
int last_volt = get_avg_voltage(); |
|
581 |
|
|
582 |
|
|
583 |
while(1) |
|
584 |
{ |
|
585 |
/*GIMSK = (_BV(PCIE0)); //enable PCINT interrupts |
|
586 |
sleep_cpu();*/ |
|
587 |
|
|
588 |
PORTB=0;//clear outputs |
|
589 |
|
|
590 |
GIMSK = 0; |
|
591 |
|
|
592 |
error=0; |
|
593 |
|
|
594 |
OCR1B = 0; |
|
595 |
|
|
596 |
//wait for 12v source |
|
597 |
|
|
598 |
while(!supply_voltage()) { |
|
599 |
if (!noVoltagePrintFlag) { |
|
600 |
tempData[0] = 'N'; |
|
601 |
tempData[1] = 'N'; |
|
602 |
tempData[2] = 'N'; |
|
603 |
tempData[3] = 'N'; |
|
604 |
tempData[4] = 'N'; |
|
605 |
i2c_putpacket(0x01, tempData, 5); |
|
606 |
noVoltagePrintFlag = 1; |
|
607 |
} |
|
608 |
} |
|
609 |
|
|
610 |
noVoltagePrintFlag = 0; |
|
611 |
|
|
612 |
//Contact |
|
613 |
tempData[0] = 'C'; |
|
614 |
tempData[1] = 'C'; |
|
615 |
tempData[2] = 'C'; |
|
616 |
tempData[3] = 'C'; |
|
617 |
tempData[4] = 'C'; |
|
618 |
i2c_putpacket(0x01, tempData, 5); |
|
619 |
|
|
620 |
PORTA |= _BV(debug_12in); |
|
621 |
|
|
622 |
abs_time=1; |
|
623 |
|
|
624 |
//--------------FAST CHARGE----------------------- |
|
625 |
//split seconds into eights as following: |
|
626 |
//1: abs_volt |
|
627 |
//2: reg |
|
628 |
//3: abs_temp |
|
629 |
//4: reg |
|
630 |
//5: abs_volt |
|
631 |
//6: reg |
|
632 |
//7: abs_temp |
|
633 |
//between seconds: abs time and minute checks, which takes an extra 8th |
|
634 |
status = FAST_CHARGE; |
|
635 |
|
|
636 |
PORTB |= _BV(LED2); |
|
637 |
|
|
638 |
while(status == FAST_CHARGE) |
|
639 |
{ |
|
640 |
|
|
641 |
if(!supply_voltage()) |
|
642 |
{ |
|
643 |
|
|
644 |
|
|
645 |
send_err(); |
|
646 |
//Lost Contact |
|
647 |
tempData[0] = 'N'; |
|
648 |
tempData[1] = 'N'; |
|
649 |
tempData[2] = 'N'; |
|
650 |
tempData[3] = 'N'; |
|
651 |
tempData[4] = 'N'; |
|
652 |
i2c_putpacket(0x01, tempData, 5); |
|
653 |
|
|
654 |
PORTA &= ~_BV(debug_12in); |
|
655 |
while(!supply_voltage()); |
|
656 |
|
|
657 |
//Contact again |
|
658 |
tempData[0] = 'C'; |
|
659 |
tempData[1] = 'C'; |
|
660 |
tempData[2] = 'C'; |
|
661 |
tempData[3] = 'C'; |
|
662 |
tempData[4] = 'C'; |
|
663 |
i2c_putpacket(0x01, tempData, 5); |
|
664 |
|
|
665 |
PORTA |= _BV(debug_12in); |
|
666 |
clear_err(); |
|
667 |
} |
|
668 |
|
|
669 |
check_voltage(); |
|
670 |
wait_8th(); |
|
671 |
regulate_current(FAST_I); |
|
672 |
wait_8th(); |
|
673 |
check_temperature(); |
|
674 |
wait_8th(); |
|
675 |
regulate_current(FAST_I); |
|
676 |
wait_8th(); |
|
677 |
check_voltage(); |
|
678 |
wait_8th(); |
|
679 |
regulate_current(FAST_I); |
|
680 |
wait_8th(); |
|
681 |
check_temperature(); |
|
682 |
wait_8th(); |
|
683 |
|
|
684 |
#ifdef TRICKLE |
|
685 |
|
|
686 |
if(abs_time > 9600) //90 minute time limit |
|
687 |
{ |
|
688 |
OCR1A = 32; |
|
689 |
send_done(); |
|
690 |
PORTA |= _BV(debug_time); |
|
691 |
break; |
|
692 |
} |
|
693 |
|
|
694 |
#else |
|
695 |
|
|
696 |
if(abs_time > 43200) //90 minute time limit |
|
697 |
{ |
|
698 |
OCR1A = 32; |
|
699 |
send_err(); |
|
700 |
PORTA |= _BV(debug_time); |
|
701 |
break; |
|
702 |
} |
|
703 |
|
|
704 |
//minute checks |
|
705 |
if( (abs_time >> 3)%55 == 0/* && steady_current*/) |
|
706 |
{ |
|
707 |
PORTA ^= _BV(debug_time); |
|
708 |
|
|
709 |
temp = get_avg_temperature(); |
|
710 |
wait_8th(); //to avoid interference |
|
711 |
volt = get_avg_voltage(); |
|
712 |
|
|
713 |
OCR1A = volt >> 2; |
|
714 |
|
|
715 |
//seems to be some random drops when connected to a power supply |
|
716 |
//may need a fudge factor but maybe not becuase voltage should be climbing during charge |
|
717 |
if(volt < last_volt - MAX_DV) |
|
718 |
{ |
|
719 |
PORTA |= _BV(debug_volt); |
|
720 |
if(last_DV) |
|
721 |
{ |
|
722 |
OCR1A = 64; |
|
723 |
|
|
724 |
send_done(); |
|
725 |
PORTA |= _BV(debug_volt); |
|
726 |
status = TRICKLE_CHARGE; |
|
727 |
} |
|
728 |
else |
|
729 |
last_DV=1; |
|
730 |
|
|
731 |
} |
|
732 |
else |
|
733 |
{ |
|
734 |
last_DV=0; |
|
735 |
PORTA &= ~_BV(debug_volt); |
|
736 |
} |
|
737 |
|
|
738 |
|
|
739 |
if(temp < last_temp - MAX_DT) |
|
740 |
{ |
|
741 |
PORTA |= _BV(debug_temp); |
|
742 |
if(last_DT) |
|
743 |
{ |
|
744 |
OCR1A = 128; |
|
745 |
|
|
746 |
send_done(); |
|
747 |
PORTA |= _BV(debug_temp); |
|
748 |
status = TRICKLE_CHARGE; |
|
749 |
} |
|
750 |
else |
|
751 |
last_DT=1; |
|
752 |
} |
|
753 |
else |
|
754 |
{ |
|
755 |
last_DT=0; |
|
756 |
PORTA &= ~_BV(debug_temp); |
|
757 |
} |
|
758 |
|
|
759 |
last_volt = volt; |
|
760 |
last_temp = temp; |
|
761 |
} |
|
762 |
#endif |
|
763 |
|
|
764 |
} |
|
765 |
if (error) { |
|
766 |
//We have an error...let's bail out of this ship captain! |
|
767 |
tempData[0] = 'F'; |
|
768 |
tempData[1] = 'F'; |
|
769 |
tempData[2] = 'F'; |
|
770 |
tempData[3] = 'F'; |
|
771 |
tempData[4] = 'F'; |
|
772 |
i2c_putpacket(0x01, tempData, 5); |
|
773 |
} |
|
774 |
|
|
775 |
//PORTB ^= _BV(LED2); |
|
776 |
|
|
777 |
} |
|
778 |
|
|
779 |
|
|
780 |
return 1; |
|
781 |
} |
|
782 |
|
|
783 |
ISR(TIMER0_OVF_vect) |
|
784 |
{ |
|
785 |
if(error) |
|
786 |
PORTB ^= (_BV(LED1)|_BV(LED2)); |
|
787 |
|
|
788 |
interrupt_count--; |
|
789 |
if(interrupt_count==0) |
|
790 |
{ |
|
791 |
abs_time++; |
|
792 |
new_second=1; |
|
793 |
|
|
794 |
interrupt_count=INT_COUNT; |
|
795 |
} |
|
796 |
} |
|
797 |
|
|
798 |
ISR(PCINT_vect){;} //so the interrupt doesnt go to the reset vector |
branches/autonomous_recharging/code/projects/autonomous_recharging/archs/USI_TWI_Slave.h | ||
---|---|---|
1 |
// This file has been prepared for Doxygen automatic documentation generation. |
|
2 |
/*! \file ******************************************************************** |
|
3 |
* |
|
4 |
* Atmel Corporation |
|
5 |
* |
|
6 |
* File : USI_TWI_Slave.h |
|
7 |
* Compiler : IAR EWAAVR 4.11A |
|
8 |
* Revision : $Revision: 1.14 $ |
|
9 |
* Date : $Date: Friday, December 09, 2005 17:25:38 UTC $ |
|
10 |
* Updated by : $Author: jtyssoe $ |
|
11 |
* |
|
12 |
* Support mail : avr@atmel.com |
|
13 |
* |
|
14 |
* Supported devices : All device with USI module can be used. |
|
15 |
* The example is written for the ATmega169, ATtiny26 & ATtiny2313 |
|
16 |
* |
|
17 |
* AppNote : AVR312 - Using the USI module as a TWI slave |
|
18 |
* |
|
19 |
* Description : Header file for USI_TWI driver |
|
20 |
* |
|
21 |
* |
|
22 |
* |
|
23 |
****************************************************************************/ |
|
24 |
|
|
25 |
|
|
26 |
|
|
27 |
//! Prototypes |
|
28 |
void USI_TWI_Slave_Initialise( unsigned char ); |
|
29 |
void USI_TWI_Transmit_Byte( unsigned char ); |
|
30 |
unsigned char USI_TWI_Receive_Byte( void ); |
|
31 |
unsigned char USI_TWI_Data_In_Receive_Buffer( void ); |
|
32 |
void Timer_Init(void); |
|
33 |
|
|
34 |
#define TRUE 1 |
|
35 |
#define FALSE 0 |
|
36 |
|
|
37 |
typedef unsigned char uint8_t; |
|
38 |
|
|
39 |
////////////////////////////////////////////////////////////////// |
|
40 |
///////////////// Driver Buffer Definitions ////////////////////// |
|
41 |
////////////////////////////////////////////////////////////////// |
|
42 |
// 1,2,4,8,16,32,64,128 or 256 bytes are allowed buffer sizes |
|
43 |
|
|
44 |
#define TWI_RX_BUFFER_SIZE (16) |
|
45 |
#define TWI_RX_BUFFER_MASK ( TWI_RX_BUFFER_SIZE - 1 ) |
|
46 |
|
|
47 |
#if ( TWI_RX_BUFFER_SIZE & TWI_RX_BUFFER_MASK ) |
|
48 |
#error TWI RX buffer size is not a power of 2 |
|
49 |
#endif |
|
50 |
|
|
51 |
// 1,2,4,8,16,32,64,128 or 256 bytes are allowed buffer sizes |
|
52 |
|
|
53 |
#define TWI_TX_BUFFER_SIZE (16) |
|
54 |
#define TWI_TX_BUFFER_MASK ( TWI_TX_BUFFER_SIZE - 1 ) |
|
55 |
|
|
56 |
#if ( TWI_TX_BUFFER_SIZE & TWI_TX_BUFFER_MASK ) |
|
57 |
#error TWI TX buffer size is not a power of 2 |
|
58 |
#endif |
|
59 |
|
|
60 |
|
|
61 |
|
|
62 |
#define USI_SLAVE_CHECK_ADDRESS (0x00) |
|
63 |
#define USI_SLAVE_SEND_DATA (0x01) |
|
64 |
#define USI_SLAVE_REQUEST_REPLY_FROM_SEND_DATA (0x02) |
|
65 |
#define USI_SLAVE_CHECK_REPLY_FROM_SEND_DATA (0x03) |
|
66 |
#define USI_SLAVE_REQUEST_DATA (0x04) |
|
67 |
#define USI_SLAVE_GET_DATA_AND_SEND_ACK (0x05) |
|
68 |
|
|
69 |
#define DDR_USI DDRB |
|
70 |
#define PORT_USI PORTB |
|
71 |
#define PIN_USI PINB |
|
72 |
#define PORT_USI_SDA PORTB0 |
|
73 |
#define PORT_USI_SCL PORTB2 |
|
74 |
#define PIN_USI_SDA PINB0 |
|
75 |
#define PIN_USI_SCL PINB2 |
|
76 |
#define USI_START_COND_INT USISIF |
|
77 |
#define USI_START_VECTOR USI_START_vect |
|
78 |
#define USI_OVERFLOW_VECTOR USI_OVF_vect |
|
79 |
|
|
80 |
|
|
81 |
//! Functions implemented as macros |
|
82 |
#define SET_USI_TO_SEND_ACK() \ |
|
83 |
{ \ |
|
84 |
USIDR = 0; /* Prepare ACK */ \ |
|
85 |
DDR_USI |= (1<<PORT_USI_SDA); /* Set SDA as output */ \ |
|
86 |
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \ |
|
87 |
(0x0E<<USICNT0); /* set USI counter to shift 1 bit. */ \ |
|
88 |
} |
|
89 |
|
|
90 |
#define SET_USI_TO_READ_ACK() \ |
|
91 |
{ \ |
|
92 |
DDR_USI &= ~(1<<PORT_USI_SDA); /* Set SDA as intput */ \ |
|
93 |
USIDR = 0; /* Prepare ACK */ \ |
|
94 |
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \ |
|
95 |
(0x0E<<USICNT0); /* set USI counter to shift 1 bit. */ \ |
|
96 |
} |
|
97 |
|
|
98 |
#define SET_USI_TO_TWI_START_CONDITION_MODE() \ |
|
99 |
{ \ |
|
100 |
USICR = (1<<USISIE)|(0<<USIOIE)| /* Enable Start Condition Interrupt. Disable Overflow Interrupt.*/ \ |
|
101 |
(1<<USIWM1)|(0<<USIWM0)| /* Set USI in Two-wire mode. No USI Counter overflow hold. */ \ |
|
102 |
(1<<USICS1)|(0<<USICS0)|(0<<USICLK)| /* Shift Register Clock Source = External, positive edge */ \ |
|
103 |
(0<<USITC); \ |
|
104 |
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \ |
|
105 |
(0x0<<USICNT0); \ |
|
106 |
} |
|
107 |
|
|
108 |
#define SET_USI_TO_SEND_DATA() \ |
|
109 |
{ \ |
|
110 |
DDR_USI |= (1<<PORT_USI_SDA); /* Set SDA as output */ \ |
|
111 |
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \ |
|
112 |
(0x0<<USICNT0); /* set USI to shift out 8 bits */ \ |
|
113 |
} |
|
114 |
|
|
115 |
#define SET_USI_TO_READ_DATA() \ |
|
116 |
{ \ |
|
117 |
DDR_USI &= ~(1<<PORT_USI_SDA); /* Set SDA as input */ \ |
|
118 |
USISR = (0<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| /* Clear all flags, except Start Cond */ \ |
|
119 |
(0x0<<USICNT0); /* set USI to shift out 8 bits */ \ |
|
120 |
} |
branches/autonomous_recharging/code/projects/autonomous_recharging/archs/i2c.h | ||
---|---|---|
1 |
/* i2c.h |
|
2 |
|
|
3 |
constants and stuff |
|
4 |
*/ |
|
5 |
#ifndef _I2C_H_ |
|
6 |
#define _I2C_H_ |
|
7 |
|
|
8 |
#include <avr/io.h> |
|
9 |
#include <avr/interrupt.h> |
|
10 |
#include <util/delay.h> |
|
11 |
|
|
12 |
#include "USI_TWI_Master.c" |
|
13 |
#include "USI_TWI_Slave.c" |
|
14 |
#include "i2c.c" |
|
15 |
|
|
16 |
void i2c_init(void); |
|
17 |
void i2c_putpacket(char addr, char *data, char data_size); |
|
18 |
int i2c_getpacket(char *c); |
|
19 |
void i2c_test(void); |
|
20 |
void delay_ms(int ms); |
|
21 |
|
|
22 |
#endif |
branches/autonomous_recharging/code/projects/autonomous_recharging/archs/USI_TWI_Master.h | ||
---|---|---|
1 |
|
|
2 |
|
|
3 |
|
|
4 |
/***************************************************************************** |
|
5 |
* |
|
6 |
* Atmel Corporation |
|
7 |
* |
|
8 |
* File : USI_TWI_Master.h |
|
9 |
* Compiler : IAR EWAAVR 2.28a/3.10a |
|
10 |
* Revision : $Revision: 1.11 $ |
|
11 |
* Date : $Date: Tuesday, September 13, 2005 09:09:36 UTC $ |
|
12 |
* Updated by : $Author: jtyssoe $ |
|
13 |
* |
|
14 |
* Support mail : avr@atmel.com |
|
15 |
* |
|
16 |
* Supported devices : All device with USI module can be used. |
|
17 |
* The example is written for the ATmega169, ATtiny26 and ATtiny2313 |
|
18 |
* |
|
19 |
* AppNote : AVR310 - Using the USI module as a TWI Master |
|
20 |
* |
|
21 |
* Description : This is an implementation of an TWI master using |
|
22 |
* the USI module as basis. The implementation assumes the AVR to |
|
23 |
* be the only TWI master in the system and can therefore not be |
|
24 |
* used in a multi-master system. |
|
25 |
* Usage : Initialize the USI module by calling the USI_TWI_Master_Initialise() |
|
26 |
* function. Hence messages/data are transceived on the bus using |
|
27 |
* the USI_TWI_Start_Transceiver_With_Data() function. If the transceiver |
|
28 |
* returns with a fail, then use USI_TWI_Get_Status_Info to evaluate the |
|
29 |
* couse of the failure. |
|
30 |
* |
|
31 |
****************************************************************************/ |
|
32 |
|
|
33 |
//********** Defines **********// |
|
34 |
|
|
35 |
// Defines controlling timing limits |
|
36 |
//#define TWI_FAST_MODE |
|
37 |
|
|
38 |
//#define SYS_CLK 4000.0 // [kHz] |
|
39 |
|
|
40 |
//Note, this is only a variable that determines how long to delay between |
|
41 |
// individual bits of I2C send. This has been tested down to 1MHz and it works. |
|
42 |
// It is possible that even slower speeds can be obtained. |
|
43 |
#define SYS_CLK 1.0 // [mHz] |
|
44 |
|
|
45 |
// TWI FAST mode timing limits. SCL = 100-400kHz |
|
46 |
//#define T2_TWI ((SYS_CLK *1300) /1000000) +1 // >1,3us |
|
47 |
//#define T4_TWI ((SYS_CLK * 600) /1000000) +1 // >0,6us |
|
48 |
|
|
49 |
|
|
50 |
//This may or may not make it faster. Uncomfirmed. But it works. |
|
51 |
#define T2_TWI 0.000001 |
|
52 |
#define T4_TWI 0.000001 |
|
53 |
|
|
54 |
// TWI STANDARD mode timing limits. SCL <= 100kHz |
|
55 |
//#define T2_TWI ((SYS_CLK *4700) /1000000) +1 // >4,7us |
|
56 |
//#define T4_TWI ((SYS_CLK *4000) /1000000) +1 // >4,0us |
|
57 |
|
|
58 |
//USI_TWI messages and flags and bit masks |
|
59 |
//#define SUCCESS 7 |
|
60 |
//#define MSG 0 |
|
61 |
/**************************************************************************** |
|
62 |
Bit and byte definitions |
|
63 |
****************************************************************************/ |
|
64 |
#define TWI_READ_BIT 0 // Bit position for R/W bit in "address byte". |
|
65 |
#define TWI_ADR_BITS 1 // Bit position for LSB of the slave address bits in the init byte. |
|
66 |
#define TWI_NACK_BIT 0 // Bit position for (N)ACK bit. |
|
67 |
|
|
68 |
#define USI_TWI_NO_DATA 0x00 // Transmission buffer is empty |
|
69 |
#define USI_TWI_DATA_OUT_OF_BOUND 0x01 // Transmission buffer is outside SRAM space |
|
70 |
#define USI_TWI_UE_START_CON 0x02 // Unexpected Start Condition |
|
71 |
#define USI_TWI_UE_STOP_CON 0x03 // Unexpected Stop Condition |
|
72 |
#define USI_TWI_UE_DATA_COL 0x04 // Unexpected Data Collision (arbitration) |
|
73 |
#define USI_TWI_NO_ACK_ON_DATA 0x05 // The slave did not acknowledge all data |
|
74 |
#define USI_TWI_NO_ACK_ON_ADDRESS 0x06 // The slave did not acknowledge the address |
|
75 |
#define USI_TWI_MISSING_START_CON 0x07 // Generated Start Condition not detected on bus |
|
76 |
#define USI_TWI_MISSING_STOP_CON 0x08 // Generated Stop Condition not detected on bus |
|
77 |
|
|
78 |
// Device dependant defines |
|
79 |
#define DDR_USI DDRB |
|
80 |
#define PORT_USI PORTB |
|
81 |
#define PIN_USI PINB |
|
82 |
#define PORT_USI_SDA PORTB0 |
|
83 |
#define PORT_USI_SCL PORTB2 |
|
84 |
#define PIN_USI_SDA PINB0 |
|
85 |
#define PIN_USI_SCL PINB2 |
|
86 |
|
|
87 |
// General defines |
|
88 |
#define TRUE 1 |
|
89 |
#define FALSE 0 |
|
90 |
|
|
91 |
//********** Prototypes **********// |
|
92 |
|
|
93 |
void USI_TWI_Master_Initialise( void ); |
|
94 |
unsigned char USI_TWI_Start_Transceiver_With_Data( unsigned char * , unsigned char ); |
|
95 |
unsigned char USI_TWI_Get_State_Info( void ); |
branches/autonomous_recharging/code/projects/autonomous_recharging/archs/homing stop/stop.c | ||
---|---|---|
1 |
#include<avr/io.h> |
|
2 |
#include "i2c.h" |
|
3 |
|
|
4 |
#define LED1 PB4 //Green |
|
5 |
#define LED2 PB5 //Red |
|
6 |
|
|
7 |
int main( void ) |
|
8 |
{ |
|
9 |
DDRB = _BV(PB0) | _BV(PB5) | _BV(PB4); |
|
10 |
i2c_init(); |
|
11 |
|
|
12 |
/*tempData[0] = 'C'; |
|
13 |
tempData[1] = abs_time>>8; |
|
14 |
tempData[2] = abs_time&0xFF; |
|
15 |
i2c_putpacket(0x01, tempData, 3);*/ |
|
16 |
|
|
17 |
char data[2]; |
|
18 |
data[0]=I2C_MSG_DATA; |
|
19 |
|
|
20 |
while(1) |
|
21 |
{ |
|
22 |
PORTB=_BV(LED2); |
|
23 |
while(1) |
|
24 |
{ |
|
25 |
if(PINB & _BV(PB6)) |
|
26 |
{ |
|
27 |
PORTB = _BV(LED1); |
|
28 |
//This is a junk byte. For some reason the first packet is always ignored???? |
|
29 |
data[1] = 'a'; |
|
30 |
i2c_putpacket(0x01, data, 2); |
|
31 |
data[1]=I2C_MSG_BATTERY_CHARGING; |
|
32 |
i2c_putpacket(0x01, data, 2); |
|
33 |
break; |
|
34 |
} |
|
35 |
else |
|
36 |
{ |
|
37 |
data[1]=I2C_MSG_NO_CONTACT; |
|
38 |
i2c_putpacket(0x01, data, 2); |
|
39 |
} |
|
40 |
} |
|
41 |
|
|
42 |
for(int i=0;i<5000;i++) |
|
43 |
{ |
|
44 |
delay_ms(1); |
|
45 |
if(! PINB & _BV(PB6)) |
|
46 |
{ |
|
47 |
PORTB = _BV(LED2); |
|
48 |
data[1]=I2C_MSG_CONTACT_ERROR; |
|
49 |
i2c_putpacket(0x01, data, 2); |
|
50 |
|
|
51 |
while(! PINB & _BV(PB6)); |
|
52 |
break; |
|
53 |
} |
|
54 |
|
|
55 |
} |
|
56 |
|
|
57 |
data[1]=I2C_MSG_BATTERY_FULL; |
|
58 |
i2c_putpacket(0x01, data, 2); |
|
59 |
} |
|
60 |
|
|
61 |
} |
branches/autonomous_recharging/code/projects/autonomous_recharging/archs/homing stop/Makefile | ||
---|---|---|
1 |
# Hey Emacs, this is a -*- makefile -*- |
|
2 |
#---------------------------------------------------------------------------- |
|
3 |
# WinAVR Makefile Template written by Eric B. Weddington, J?rg Wunsch, et al. |
|
4 |
# |
|
5 |
# Released to the Public Domain |
|
6 |
# |
|
7 |
# Additional material for this makefile was written by: |
|
8 |
# Peter Fleury |
|
9 |
# Tim Henigan |
|
10 |
# Colin O'Flynn |
|
11 |
# Reiner Patommel |
|
12 |
# Markus Pfaff |
|
13 |
# Sander Pool |
|
14 |
# Frederik Rouleau |
|
15 |
# |
|
16 |
#---------------------------------------------------------------------------- |
|
17 |
# On command line: |
|
18 |
# |
|
19 |
# make all = Make software. |
|
20 |
# |
|
21 |
# make clean = Clean out built project files. |
|
22 |
# |
|
23 |
# make coff = Convert ELF to AVR COFF. |
|
24 |
# |
|
25 |
# make extcoff = Convert ELF to AVR Extended COFF. |
|
26 |
# |
|
27 |
# make program = Download the hex file to the device, using avrdude. |
|
28 |
# Please customize the avrdude settings below first! |
|
29 |
# |
|
30 |
# make debug = Start either simulavr or avarice as specified for debugging, |
|
31 |
# with avr-gdb or avr-insight as the front end for debugging. |
|
32 |
# |
|
33 |
# make filename.s = Just compile filename.c into the assembler code only. |
|
34 |
# |
|
35 |
# make filename.i = Create a preprocessed source file for use in submitting |
|
36 |
# bug reports to the GCC project. |
|
37 |
# |
|
38 |
# To rebuild project do "make clean" then "make all". |
|
39 |
#---------------------------------------------------------------------------- |
|
40 |
|
|
41 |
|
|
42 |
# MCU name |
|
43 |
MCU = attiny861 |
|
44 |
|
|
45 |
|
|
46 |
# Processor frequency. |
|
47 |
# This will define a symbol, F_CPU, in all source code files equal to the |
|
48 |
# processor frequency. You can then use this symbol in your source code to |
|
49 |
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done |
|
50 |
# automatically to create a 32-bit value in your source code. |
|
51 |
F_CPU = 8000000 |
|
52 |
|
|
53 |
|
|
54 |
# Output format. (can be srec, ihex, binary) |
|
55 |
FORMAT = ihex |
|
56 |
|
|
57 |
|
|
58 |
# Target file name (without extension). |
|
59 |
TARGET = stop |
|
60 |
|
|
61 |
|
|
62 |
# List C source files here. (C dependencies are automatically generated.) |
|
63 |
SRC = $(TARGET).c |
|
64 |
|
|
65 |
|
|
66 |
# List Assembler source files here. |
|
67 |
# Make them always end in a capital .S. Files ending in a lowercase .s |
|
68 |
# will not be considered source files but generated files (assembler |
|
69 |
# output from the compiler), and will be deleted upon "make clean"! |
|
70 |
# Even though the DOS/Win* filesystem matches both .s and .S the same, |
|
71 |
# it will preserve the spelling of the filenames, and gcc itself does |
|
72 |
# care about how the name is spelled on its command-line. |
|
73 |
ASRC = |
|
74 |
|
|
75 |
|
|
76 |
# Optimization level, can be [0, 1, 2, 3, s]. |
|
77 |
# 0 = turn off optimization. s = optimize for size. |
|
78 |
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) |
|
79 |
OPT = s |
|
80 |
|
|
81 |
|
|
82 |
# Debugging format. |
|
83 |
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs. |
|
84 |
# AVR Studio 4.10 requires dwarf-2. |
|
85 |
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run. |
|
86 |
DEBUG = dwarf-2 |
|
87 |
|
|
88 |
|
|
89 |
# List any extra directories to look for include files here. |
|
90 |
# Each directory must be seperated by a space. |
|
91 |
# Use forward slashes for directory separators. |
|
92 |
# For a directory that has spaces, enclose it in quotes. |
|
93 |
#EXTRAINCDIRS = C:\WinAVR\include\fwr |
|
94 |
|
|
95 |
|
|
96 |
# Compiler flag to set the C Standard level. |
|
97 |
# c89 = "ANSI" C |
|
98 |
# gnu89 = c89 plus GCC extensions |
|
99 |
# c99 = ISO C99 standard (not yet fully implemented) |
|
100 |
# gnu99 = c99 plus GCC extensions |
|
101 |
CSTANDARD = -std=gnu99 |
|
102 |
|
|
103 |
|
|
104 |
# Place -D or -U options here |
|
105 |
CDEFS = -DF_CPU=$(F_CPU)UL |
|
106 |
|
|
107 |
|
|
108 |
# Place -I options here |
|
109 |
CINCS = |
|
110 |
|
|
111 |
|
|
112 |
|
|
113 |
#---------------- Compiler Options ---------------- |
|
114 |
# -g*: generate debugging information |
|
115 |
# -O*: optimization level |
|
116 |
# -f...: tuning, see GCC manual and avr-libc documentation |
Also available in: Unified diff