Subversion Repositories Projects

Rev

Rev 771 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 771 Rev 902
1
/****************************************************************************
1
/****************************************************************************
2
 *   Copyright (C) 2009-2010 by Claas Anders "CaScAdE" Rathje               *
2
 *   Copyright (C) 2009-2011 by Claas Anders "CaScAdE" Rathje               *
3
 *   admiralcascade@gmail.com                                               *
3
 *   admiralcascade@gmail.com                                               *
4
 *   Project-URL: http://www.mylifesucks.de/oss/c-strom/                    *
4
 *   Project-URL: http://www.mylifesucks.de/oss/c-strom/                    *
5
 *                                                                          *
5
 *                                                                          *
6
 *   This program is free software; you can redistribute it and/or modify   *
6
 *   This program is free software; you can redistribute it and/or modify   *
7
 *   it under the terms of the GNU General Public License as published by   *
7
 *   it under the terms of the GNU General Public License as published by   *
8
 *   the Free Software Foundation; either version 2 of the License.         *
8
 *   the Free Software Foundation; either version 2 of the License.         *
9
 *                                                                          *
9
 *                                                                          *
10
 *   This program is distributed in the hope that it will be useful,        *
10
 *   This program is distributed in the hope that it will be useful,        *
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
11
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         *
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
12
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
13
 *   GNU General Public License for more details.                           *
13
 *   GNU General Public License for more details.                           *
14
 *                                                                          *
14
 *                                                                          *
15
 *   You should have received a copy of the GNU General Public License      *
15
 *   You should have received a copy of the GNU General Public License      *
16
 *   along with this program; if not, write to the                          *
16
 *   along with this program; if not, write to the                          *
17
 *   Free Software Foundation, Inc.,                                        *
17
 *   Free Software Foundation, Inc.,                                        *
18
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.              *
18
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.              *
19
 *                                                                          *
19
 *                                                                          *
20
 *   Thanks to:                                                             *
20
 *   Thanks to:                                                             *
21
 *   Klaus "akku" Buettner for the hardware                                 *
21
 *   Klaus "akku" Buettner for the hardware                                 *
22
 *   All people at http://www.rn-wissen.de especially for the i2c stuff     *
22
 *   All people at http://www.rn-wissen.de especially for the i2c stuff     *
23
 *                                                                          *
23
 *                                                                          *
24
 ****************************************************************************/
24
 ****************************************************************************/
25
 
25
 
26
#include <avr/io.h>
26
#include <avr/io.h>
27
#include <avr/eeprom.h>
27
#include <avr/eeprom.h>
28
#include <avr/pgmspace.h>
28
#include <avr/pgmspace.h>
29
#include <avr/interrupt.h>
29
#include <avr/interrupt.h>
30
#include <util/delay.h>
30
#include <util/delay.h>
31
#include <stdlib.h>
31
#include <stdlib.h>
32
#include <string.h>
32
#include <string.h>
33
#include "C-Strom.h"
33
#include "C-Strom.h"
34
#include "spi_union.h"
34
#include "spi_union.h"
35
#include "i2c_slave.h"
35
#include "i2c_slave.h"
36
 
36
 
37
uint8_t EEMEM ee_checkbyte1 = CHECKBYTE1;
37
uint8_t EEMEM ee_checkbyte1 = CHECKBYTE1;
38
uint8_t EEMEM ee_checkbyte2 = CHECKBYTE2;
38
uint8_t EEMEM ee_checkbyte2 = CHECKBYTE2;
39
uint16_t EEMEM ee_cal_ampere = 512;
39
uint16_t EEMEM ee_cal_ampere = 512;
40
uint8_t EEMEM ee_sensor = 50;
40
uint8_t EEMEM ee_sensor = 50;
41
uint8_t EEMEM ee_prim_r1 = 47, ee_prim_r2 = 150;
41
uint8_t EEMEM ee_prim_r1 = 47, ee_prim_r2 = 150;
42
uint8_t EEMEM ee_anin_r1 = 47, ee_anin_r2 = 150;
42
uint8_t EEMEM ee_anin_r1 = 47, ee_anin_r2 = 150;
43
uint8_t EEMEM ee_config = 0;
43
uint8_t EEMEM ee_config = 0;
44
 
44
 
45
volatile uint8_t CSTROM_FLAGS = 0;
45
volatile uint8_t CSTROM_FLAGS = 0;
46
volatile uint8_t CSTROM_CONFIG = 0;
46
volatile uint8_t CSTROM_CONFIG = 0;
47
 
47
 
48
// we could use ee_cal_ampere but eeprom is slow :)
48
// we could use ee_cal_ampere but eeprom is slow :)
49
volatile uint16_t cal_ampere = 512;
49
volatile uint16_t cal_ampere = 512;
50
volatile uint8_t sensor = 50;
50
volatile uint8_t sensor = 50;
51
volatile uint8_t prim_r1 = 47, prim_r2 = 150;
51
volatile uint8_t prim_r1 = 47, prim_r2 = 150;
52
volatile uint8_t anin_r1 = 47, anin_r2 = 150;
52
volatile uint8_t anin_r1 = 47, anin_r2 = 150;
53
volatile int16_t ampere, volt, anin_volt, transfer_ampere;
53
volatile int16_t ampere, volt, anin_volt, transfer_ampere;
54
volatile int32_t transfer_mah, mah;
54
volatile int32_t transfer_mah, mah;
55
volatile int16_t average_ampere = 0;
55
volatile int16_t average_ampere = 0;
56
volatile uint8_t hwver = 10;
56
volatile uint8_t hwver = 10;
57
// global space for int conversion to string
57
// global space for int conversion to string
58
char s[10];
58
char s[10];
59
 
59
 
60
// spi buffer
60
// spi buffer
61
union SPI_buffer_t SPI_buffer;
61
union SPI_buffer_t SPI_buffer;
62
 
62
 
63
// PD7 High
63
// PD7 High
64
void PD7_H() {
64
void PD7_H() {
65
        PORTD |=  (1 << PD7);
65
        PORTD |=  (1 << PD7);
66
}
66
}
67
 
67
 
68
// PD7 Low
68
// PD7 Low
69
void PD7_L() {
69
void PD7_L() {
70
        PORTD &= ~(1 << PD7);
70
        PORTD &= ~(1 << PD7);
71
}
71
}
72
 
72
 
73
void (*LED_ON)(void) = PD7_H;
73
void (*LED_ON)(void) = PD7_H;
74
void (*LED_OFF)(void) = PD7_L;
74
void (*LED_OFF)(void) = PD7_L;
75
 
75
 
76
 
76
 
77
void ampere_calibrate();
77
void ampere_calibrate();
78
void save_eeprom();
78
void save_eeprom();
79
void help(uint8_t);
79
void help(uint8_t);
80
 
80
 
81
/*ISR(__vector_default) {
81
/*ISR(__vector_default) {
82
    asm("nop");
82
    asm("nop");
83
}*/
83
}*/
84
 
84
 
85
/**
85
/**
86
 * decimal itoa for 10th values
86
 * decimal itoa for 10th values
87
 */
87
 */
88
char *itoa_dec(int val, char* s) {
88
char *itoa_dec(int val, char* s) {
89
        itoa(val, s, 10);
89
        itoa(val, s, 10);
90
        //char x = 0;
90
        //char x = 0;
91
        for (uint8_t i = 0; i < 9; i++) {
91
        for (uint8_t i = 0; i < 9; i++) {
92
                if (s[i] == 0 && i > 0) {
92
                if (s[i] == 0 && i > 0) {
93
                        if (i == 1) {
93
                        if (i == 1) {
94
                                s[i+1] = s[i-1];       
94
                                s[i+1] = s[i-1];       
95
                                s[i-1] = '0';
95
                                s[i-1] = '0';
96
                                s[i] = '.';
96
                                s[i] = '.';
97
                                s[i+2] = 0;    
97
                                s[i+2] = 0;    
98
                        } else {
98
                        } else {
99
                                s[i] = s[i-1];
99
                                s[i] = s[i-1];
100
                                s[i-1] = '.';
100
                                s[i-1] = '.';
101
                                s[i+1] = 0;
101
                                s[i+1] = 0;
102
                        }
102
                        }
103
                        break;
103
                        break;
104
                }
104
                }
105
        }
105
        }
106
        return s;
106
        return s;
107
}
107
}
108
 
108
 
109
/**
109
/**
110
 * init uart
110
 * init uart
111
 */
111
 */
112
void uart_init() {
112
void uart_init() {
113
    UBRRL = (F_CPU / (16UL * BAUD_RATE)) - 1;
113
    UBRRL = (F_CPU / (16UL * BAUD_RATE)) - 1;
114
 
114
 
115
    // Enable receiver and transmitter; enable RX interrupt
115
    // Enable receiver and transmitter; enable RX interrupt
116
    UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
116
    UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
117
 
117
 
118
    //asynchronous 8N1
118
    //asynchronous 8N1
119
    UCSRC = (1 << URSEL) | (3 << UCSZ0);
119
    UCSRC = (1 << URSEL) | (3 << UCSZ0);
120
}
120
}
121
 
121
 
122
/**
122
/**
123
 * send a single <character> through uart
123
 * send a single <character> through uart
124
 */
124
 */
125
void uart_putc(unsigned char character) {
125
void uart_putc(unsigned char character) {
126
    // wait until UDR ready
126
    // wait until UDR ready
127
    while (!(UCSRA & (1 << UDRE)));
127
    while (!(UCSRA & (1 << UDRE)));
128
    UDR = character;
128
    UDR = character;
129
}
129
}
130
 
130
 
131
/**
131
/**
132
 * send a <string> throught uart
132
 * send a <string> throught uart
133
 */
133
 */
134
void uart_puts(char *s) {
134
void uart_puts(char *s) {
135
    while (*s) {
135
    while (*s) {
136
        uart_putc(*s);
136
        uart_putc(*s);
137
        s++;
137
        s++;
138
    }
138
    }
139
}
139
}
140
 
140
 
141
/**
141
/**
142
 * send a <string> from pgm space throught uart
142
 * send a <string> from pgm space throught uart
143
 */
143
 */
144
void uart_puts_pgm(char *string) {
144
void uart_puts_pgm(char *string) {
145
        while (pgm_read_byte(string) != 0x00)
145
        while (pgm_read_byte(string) != 0x00)
146
                uart_putc(pgm_read_byte(string++));
146
                uart_putc(pgm_read_byte(string++));
147
}
147
}
148
 
148
 
149
/**
149
/**
150
 * change the sensor type
150
 * change the sensor type
151
 */
151
 */
152
void sensor_change(uint8_t new_value) {
152
void sensor_change(uint8_t new_value) {
153
        if (new_value < 10) new_value = 0;
153
        if (new_value < 10) new_value = 0;
154
        else if (new_value > 250) new_value = 250;
154
        else if (new_value > 250) new_value = 250;
155
        sensor = new_value;
155
        sensor = new_value;
156
        uart_puts_pgm(PSTR("\r\nSensor is now: "));
156
        uart_puts_pgm(PSTR("\r\nSensor is now: "));
157
        uart_puts(itoa(sensor, s, 10));
157
        uart_puts(itoa(sensor, s, 10));
158
        uart_puts("A\r\n");
158
        uart_puts("A\r\n");
159
}
159
}
160
 
160
 
161
/**
161
/**
162
 * change the r2 value
162
 * change the r2 value
163
 */
163
 */
164
void r2_change(uint8_t which, uint8_t new_value) {     
164
void r2_change(uint8_t which, uint8_t new_value) {     
165
        if (which == V_ANIN) {         
165
        if (which == V_ANIN) {         
166
                uart_puts_pgm(PSTR("\r\nANIN R2 is now: "));
166
                uart_puts_pgm(PSTR("\r\nANIN R2 is now: "));
167
                anin_r2 = new_value;
167
                anin_r2 = new_value;
168
                uart_puts(itoa_dec(anin_r2, s));
168
                uart_puts(itoa_dec(anin_r2, s));
169
        } else {
169
        } else {
170
                uart_puts_pgm(PSTR("\r\nPRIMARY R2 is now: "));
170
                uart_puts_pgm(PSTR("\r\nPRIMARY R2 is now: "));
171
                prim_r2 = new_value;
171
                prim_r2 = new_value;
172
                uart_puts(itoa_dec(prim_r2, s));
172
                uart_puts(itoa_dec(prim_r2, s));
173
        }
173
        }
174
        uart_puts_pgm(PSTR("kOhm\r\n"));
174
        uart_puts_pgm(PSTR("kOhm\r\n"));
175
}
175
}
176
 
176
 
177
/**
177
/**
178
 * enable/disable TWI
178
 * enable/disable TWI
179
 */
179
 */
180
void twi_change() {    
180
void twi_change() {    
181
        uart_puts_pgm(PSTR("\r\nTWI turned "));
181
        uart_puts_pgm(PSTR("\r\nTWI turned "));
182
        if (CSTROM_CONFIG & CSTROM_TWI) {
182
        if (CSTROM_CONFIG & CSTROM_TWI) {
183
                uart_puts_pgm(PSTR("ON"));
183
                uart_puts_pgm(PSTR("ON"));
184
        } else {
184
        } else {
185
                uart_puts_pgm(PSTR("OFF"));
185
                uart_puts_pgm(PSTR("OFF"));
186
        }
186
        }
187
        uart_puts_pgm(PSTR(". Please restart...\r\n"));
187
        uart_puts_pgm(PSTR(". Please restart...\r\n"));
188
}
188
}
189
 
189
 
190
 
190
 
191
 
191
 
192
 
192
 
193
/**
193
/**
194
 * Interrupt handler for received data through UART1
194
 * Interrupt handler for received data through UART1
195
 */
195
 */
196
SIGNAL(SIG_UART_RECV) {
196
SIGNAL(SIG_UART_RECV) {
197
        unsigned char c = UDR;
197
        unsigned char c = UDR;
198
        switch (c) {
198
        switch (c) {
199
                case 'c':
199
                case 'c':
200
                        ampere_calibrate();
200
                        ampere_calibrate();
201
                        break;
201
                        break;
202
                case 's':
202
                case 's':
203
                        save_eeprom();
203
                        save_eeprom();
204
                        break;
204
                        break;
205
                case '+':
205
                case '+':
206
                        sensor_change(100);
206
                        sensor_change(100);
207
                        break;
207
                        break;
208
                case '-':
208
                case '-':
209
                        sensor_change(50);
209
                        sensor_change(50);
210
                        break;
210
                        break;
211
                case 'e':
211
                case 'e':
212
                        if (hwver == 11) r2_change(V_ANIN, anin_r2 + 1);
212
                        if (hwver == 11) r2_change(V_ANIN, anin_r2 + 1);
213
                        break;
213
                        break;
214
                case 'd':
214
                case 'd':
215
                        if (hwver == 11) r2_change(V_ANIN, anin_r2 - 1);
215
                        if (hwver == 11) r2_change(V_ANIN, anin_r2 - 1);
216
                        break;
216
                        break;
217
                case 'r':
217
                case 'r':
218
                        r2_change(V_PRIMARY, prim_r2 + 1);
218
                        r2_change(V_PRIMARY, prim_r2 + 1);
219
                        break;
219
                        break;
220
                case 'f':
220
                case 'f':
221
                        r2_change(V_PRIMARY, prim_r2 - 1);
221
                        r2_change(V_PRIMARY, prim_r2 - 1);
222
                        break;
222
                        break;
223
                case 'T':
223
                case 'T':
224
                        CSTROM_CONFIG ^= CSTROM_TWI;
224
                        CSTROM_CONFIG ^= CSTROM_TWI;
225
                        twi_change();
225
                        twi_change();
226
                        break;
226
                        break;
227
                case 'h':
227
                case 'h':
228
                        help(0);
228
                        help(0);
229
                        break;
229
                        break;
230
                default:
230
                default:
231
                        asm("nop"); // :-)
231
                        asm("nop"); // :-)
232
        }
232
        }
233
}
233
}
234
 
234
 
235
/**
235
/**
236
 * Interrupt handler for transmitting data through UART1
236
 * Interrupt handler for transmitting data through UART1
237
 */
237
 */
238
SIGNAL(SIG_UART_TRANS) {
238
SIGNAL(SIG_UART_TRANS) {
239
}
239
}
240
 
240
 
241
/**
241
/**
242
 * Read out the ADC channel <channel>
242
 * Read out the ADC channel <channel>
243
 */
243
 */
244
uint16_t readADC(uint8_t channel) {
244
uint16_t readADC(uint8_t channel) {
245
        uint8_t i;
245
        uint8_t i;
246
        uint16_t result = 0;
246
        uint16_t result = 0;
247
 
247
 
248
        // enable ADC and set clk div to 64
248
        // enable ADC and set clk div to 64
249
        ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
249
        ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
250
 
250
 
251
        _delay_us(5);
251
        _delay_us(5);
252
 
252
 
253
        // set up channel
253
        // set up channel
254
        ADMUX = channel;
254
        ADMUX = channel;
255
        // use internal reference
255
        // use internal reference
256
        //ADMUX |= (1<<REFS1) | (1<<REFS0);
256
        //ADMUX |= (1<<REFS1) | (1<<REFS0);
257
 
257
 
258
        // init ADC for a dummy readout
258
        // init ADC for a dummy readout
259
        ADCSRA |= (1<<ADSC);
259
        ADCSRA |= (1<<ADSC);
260
        // wait for conversion to be complete
260
        // wait for conversion to be complete
261
        while(ADCSRA & (1<<ADSC));
261
        while(ADCSRA & (1<<ADSC));
262
 
262
 
263
        // read in three times and get the average
263
        // read in three times and get the average
264
        for(i=0; i<3; i++) {
264
        for(i=0; i<3; i++) {
265
                // start conversion
265
                // start conversion
266
                ADCSRA |= (1<<ADSC);
266
                ADCSRA |= (1<<ADSC);
267
 
267
 
268
                // wait for conversion to be complete
268
                // wait for conversion to be complete
269
                while(ADCSRA & (1<<ADSC));
269
                while(ADCSRA & (1<<ADSC));
270
 
270
 
271
                // add up result
271
                // add up result
272
                result += ADCW;
272
                result += ADCW;
273
        }
273
        }
274
 
274
 
275
        // disable ADC
275
        // disable ADC
276
        ADCSRA &= ~(1<<ADEN);
276
        ADCSRA &= ~(1<<ADEN);
277
 
277
 
278
        // get average
278
        // get average
279
        result /= 3;
279
        result /= 3;
280
 
280
 
281
        return result;
281
        return result;
282
}
282
}
283
 
283
 
284
 
284
 
285
/**
285
/**
286
 * init SPI slave interrupt conrolled
286
 * init SPI slave interrupt conrolled
287
 */
287
 */
288
void Init_Slave_IntContr (void) {
288
void Init_Slave_IntContr (void) {
289
        volatile char IOReg;
289
        volatile char IOReg;
290
        // Set PB4(MISO) as output
290
        // Set PB4(MISO) as output
291
        DDRB    = (1<<PB4);
291
        DDRB    = (1<<PB4);
292
                // MOSI Pullup
292
                // MOSI Pullup
293
                PORTB |= _BV(3);
293
                PORTB |= _BV(3);
294
        // Enable SPI Interrupt and SPI in Slave Mode
294
        // Enable SPI Interrupt and SPI in Slave Mode
295
        SPCR  = (1<<SPIE)|(1<<SPE);
295
        SPCR  = (1<<SPIE)|(1<<SPE);
296
        IOReg   = SPSR; // Clear SPIF bit in SPSR
296
        IOReg   = SPSR; // Clear SPIF bit in SPSR
297
        IOReg   = SPDR;
297
        IOReg   = SPDR;
298
                SPCR |= _BV(SPIE); // duplicated
298
                SPCR |= _BV(SPIE); // duplicated
299
}
299
}
300
 
300
 
301
 
301
 
302
 
302
 
303
/**
303
/**
304
 * SPI interrupt handling
304
 * SPI interrupt handling
305
 */
305
 */
306
ISR(SPI_STC_vect) {
306
ISR(SPI_STC_vect) {
307
        LED_ON();
307
        LED_ON();
308
 
308
 
309
        unsigned char foo;
309
        unsigned char foo;
310
        foo = SPDR;
310
        foo = SPDR;
311
        //uart_putc(foo);
311
        //uart_putc(foo);
312
        switch (foo) {
312
        switch (foo) {
313
                case 'A': // requested ampere high bits for next transmission
313
                case 'A': // requested ampere high bits for next transmission
314
                        CSTROM_FLAGS |= CSTROM_SPILOCKED;
314
                        CSTROM_FLAGS |= CSTROM_SPILOCKED;
315
                        foo = SPI_buffer.buffer.c[0];
315
                        foo = SPI_buffer.buffer.c[0];
316
                        break;
316
                        break;
317
                case 'B': // requested low bits
317
                case 'B': // requested low bits
318
                        foo = SPI_buffer.buffer.c[1];
318
                        foo = SPI_buffer.buffer.c[1];
319
                        break;
319
                        break;
320
                case 'C': // wasted ampere high bits in next
320
                case 'C': // wasted ampere high bits in next
321
                        foo = SPI_buffer.buffer.c[2];
321
                        foo = SPI_buffer.buffer.c[2];
322
                        break;
322
                        break;
323
                case 'D': // 2nd highest 8bits
323
                case 'D': // 2nd highest 8bits
324
                        foo = SPI_buffer.buffer.c[3];
324
                        foo = SPI_buffer.buffer.c[3];
325
                        break;
325
                        break;
326
                case 'E': // 3rd highest 8bits
326
                case 'E': // 3rd highest 8bits
327
                        foo = SPI_buffer.buffer.c[4];
327
                        foo = SPI_buffer.buffer.c[4];
328
                        break;
328
                        break;
329
                case 'F': // lowest 8bits
329
                case 'F': // lowest 8bits
330
                        foo = SPI_buffer.buffer.c[5];
330
                        foo = SPI_buffer.buffer.c[5];
331
                        break;
331
                        break;
332
                case 'G': // lowest 8bits
332
                case 'G': // lowest 8bits
333
                        foo = SPI_buffer.buffer.c[6];
333
                        foo = SPI_buffer.buffer.c[6];
334
                        break;
334
                        break;
335
                case 'H': // lowest 8bits
335
                case 'H': // lowest 8bits
336
                        foo = SPI_buffer.buffer.c[7];
336
                        foo = SPI_buffer.buffer.c[7];
337
                        break;
337
                        break;
338
                case 'I': // challange over
338
                case 'I': // challange over
339
                        foo = 'd'; // done :)
339
                        foo = 'd'; // done :)
340
                        CSTROM_FLAGS &= ~CSTROM_SPILOCKED;
340
                        CSTROM_FLAGS &= ~CSTROM_SPILOCKED;
341
                        break;
341
                        break;
342
                default:  // what else? nothin now
342
                default:  // what else? nothin now
343
                        foo = 'X';
343
                        foo = 'X';
344
        }
344
        }
345
        // write back foo in next transmission
345
        // write back foo in next transmission
346
        SPDR = foo;
346
        SPDR = foo;
347
 
347
 
348
        //uart_putc(foo);
348
        //uart_putc(foo);
349
 
349
 
350
        LED_OFF();
350
        LED_OFF();
351
}
351
}
352
 
352
 
353
/**
353
/**
354
 * read data saved in eeprom
354
 * read data saved in eeprom
355
 */
355
 */
356
void get_eeprom() {
356
void get_eeprom() {
357
        if (eeprom_read_byte(&ee_checkbyte1) == CHECKBYTE1 && eeprom_read_byte(&ee_checkbyte2) == CHECKBYTE2) {
357
        if (eeprom_read_byte(&ee_checkbyte1) == CHECKBYTE1 && eeprom_read_byte(&ee_checkbyte2) == CHECKBYTE2) {
358
                uart_puts("\tLoading data from eeprom...");
358
                uart_puts("\tLoading data from eeprom...");
359
                sensor = eeprom_read_byte(&ee_sensor);
359
                sensor = eeprom_read_byte(&ee_sensor);
360
                cal_ampere = eeprom_read_word(&ee_cal_ampere);
360
                cal_ampere = eeprom_read_word(&ee_cal_ampere);
361
                anin_r1 = eeprom_read_byte(&ee_anin_r1);
361
                anin_r1 = eeprom_read_byte(&ee_anin_r1);
362
                anin_r2 = eeprom_read_byte(&ee_anin_r2);
362
                anin_r2 = eeprom_read_byte(&ee_anin_r2);
363
                prim_r1 = eeprom_read_byte(&ee_prim_r1);
363
                prim_r1 = eeprom_read_byte(&ee_prim_r1);
364
                prim_r2 = eeprom_read_byte(&ee_prim_r2);
364
                prim_r2 = eeprom_read_byte(&ee_prim_r2);
365
                CSTROM_CONFIG = eeprom_read_byte(&ee_config);
365
                CSTROM_CONFIG = eeprom_read_byte(&ee_config);
366
                uart_puts("done\r\n");
366
                uart_puts("done\r\n");
367
        } else {
367
        } else {
368
                uart_puts("\tNo data found in eeprom, using default data...\r\n");
368
                uart_puts("\tNo data found in eeprom, using default data...\r\n");
369
        }
369
        }
370
}
370
}
371
 
371
 
372
/**
372
/**
373
 * save data to eeprom
373
 * save data to eeprom
374
 */
374
 */
375
void save_eeprom() {
375
void save_eeprom() {
376
        uart_puts("\r\nSaving data to eeprom...");
376
        uart_puts("\r\nSaving data to eeprom...");
377
        eeprom_write_byte(&ee_checkbyte1, CHECKBYTE1);
377
        eeprom_write_byte(&ee_checkbyte1, CHECKBYTE1);
378
        eeprom_write_byte(&ee_checkbyte2, CHECKBYTE2);
378
        eeprom_write_byte(&ee_checkbyte2, CHECKBYTE2);
379
        eeprom_write_byte(&ee_sensor, sensor);
379
        eeprom_write_byte(&ee_sensor, sensor);
380
        eeprom_write_word(&ee_cal_ampere, cal_ampere);
380
        eeprom_write_word(&ee_cal_ampere, cal_ampere);
381
        //if (hwver == 11)  {
381
        //if (hwver == 11)  {
382
        // why not saving when not needed, there is space
382
        // why not saving when not needed, there is space
383
                eeprom_write_byte(&ee_anin_r1, anin_r1);
383
                eeprom_write_byte(&ee_anin_r1, anin_r1);
384
                eeprom_write_byte(&ee_anin_r2, anin_r2);               
384
                eeprom_write_byte(&ee_anin_r2, anin_r2);               
385
        //}
385
        //}
386
        eeprom_write_byte(&ee_prim_r1, prim_r1);
386
        eeprom_write_byte(&ee_prim_r1, prim_r1);
387
        eeprom_write_byte(&ee_prim_r2, prim_r2);       
387
        eeprom_write_byte(&ee_prim_r2, prim_r2);       
388
        eeprom_write_byte(&ee_config, CSTROM_CONFIG);  
388
        eeprom_write_byte(&ee_config, CSTROM_CONFIG);  
389
        uart_puts("done\r\n");
389
        uart_puts("done\r\n");
390
}
390
}
391
 
391
 
392
/**
392
/**
393
 * calibrate the current sensor... has to be 0A during this time!
393
 * calibrate the current sensor... has to be 0A during this time!
394
 */
394
 */
395
void ampere_calibrate() {
395
void ampere_calibrate() {
396
        cli();
396
        cli();
397
        uart_puts("\r\nCalibrating...");
397
        uart_puts("\r\nCalibrating...");
398
        uint16_t temp_cal = 0;
398
        uint16_t temp_cal = 0;
399
        for (uint8_t i = 0; i < 10; i++) {
399
        for (uint8_t i = 0; i < 10; i++) {
400
                temp_cal += readADC(0);
400
                temp_cal += readADC(0);
401
                uart_puts("#");
401
                uart_puts("#");
402
                _delay_ms(100);
402
                _delay_ms(100);
403
        }
403
        }
404
        cal_ampere = temp_cal / 10;
404
        cal_ampere = temp_cal / 10;
405
        uart_puts("done. Offset is now: ");
405
        uart_puts("done. Offset is now: ");
406
        uart_puts(itoa(cal_ampere, s, 10));
406
        uart_puts(itoa(cal_ampere, s, 10));
407
        uart_puts("\r\n");
407
        uart_puts("\r\n");
408
        sei();
408
        sei();
409
}
409
}
410
 
410
 
411
 
411
 
412
volatile uint16_t timer = 0, cs = 0;
412
volatile uint16_t timer = 0, cs = 0;
413
/**
413
/**
414
 * init timer0
414
 * init timer0
415
 */
415
 */
416
void init_timer0(void){
416
void init_timer0(void){
417
        // set up timer
417
        // set up timer
418
        TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64
418
        TCCR0 |= (1 << CS00) | (1 << CS01); // timer0 prescaler 64
419
        TIMSK |= (1 << TOIE0); // enable overflow timer0
419
        TIMSK |= (1 << TOIE0); // enable overflow timer0
420
}
420
}
421
 
421
 
422
/**
422
/**
423
 * timer overflow handler, should be 1ms
423
 * timer overflow handler, should be 1ms
424
 */
424
 */
425
SIGNAL(SIG_OVERFLOW0) {
425
SIGNAL(SIG_OVERFLOW0) {
426
        TCNT0 = 131; // preload
426
        TCNT0 = 131; // preload
427
        timer++;
427
        timer++;
428
        // this should be 100ms
428
        // this should be 100ms
429
        if (timer == 100) {
429
        if (timer == 100) {
430
                timer = 0;
430
                timer = 0;
431
                cs++;
431
                cs++;
432
                average_ampere += ampere;
432
                average_ampere += ampere;
433
                CSTROM_FLAGS |= CSTROM_WRITEUART;
433
                CSTROM_FLAGS |= CSTROM_WRITEUART;
434
        }
434
        }
435
        // this should be 1s
435
        // this should be 1s
436
        if (cs == 10) {
436
        if (cs == 10) {
437
                cs = 0;
437
                cs = 0;
438
                mah += average_ampere / 360;
438
                mah += average_ampere / 360;
439
                average_ampere = 0;
439
                average_ampere = 0;
440
        }
440
        }
441
}
441
}
442
 
442
 
443
/**
443
/**
444
 * write <len> through uart spaces
444
 * write <len> through uart spaces
445
 */
445
 */
446
void write_space(uint8_t len) {
446
void write_space(uint8_t len) {
447
        while (len--) {
447
        while (len--) {
448
                uart_putc(' ');
448
                uart_putc(' ');
449
        }
449
        }
450
}
450
}
451
 
451
 
452
 
452
 
453
 
453
 
454
/**
454
/**
455
 * check which hardware version we have here
455
 * check which hardware version we have here
456
 */
456
 */
457
void check_hw() {
457
void check_hw() {
458
        // check if pin was output and has pullup
458
        // check if pin was output and has pullup
459
        uint8_t old_DDRD7 =  DDRD & (1 << PD7);
459
        uint8_t old_DDRD7 =  DDRD & (1 << PD7);
460
        uint8_t old_PORTD7 =  PORTD & (1 << PD7);
460
        uint8_t old_PORTD7 =  PORTD & (1 << PD7);
461
 
461
 
462
        // if it was, make it input
462
        // if it was, make it input
463
        if (old_DDRD7) DDRD &= ~(1 << PD7); // PD7 input (LED)
463
        if (old_DDRD7) DDRD &= ~(1 << PD7); // PD7 input (LED)
464
        if (!old_PORTD7) PORTD |= (1 << PD7); // PD7 enable pullup (LED)
464
        if (!old_PORTD7) PORTD |= (1 << PD7); // PD7 enable pullup (LED)
465
       
465
       
466
 
466
 
467
        if (PIND & (1 << PD7)) {
467
        if (PIND & (1 << PD7)) {
468
                hwver = 11;
468
                hwver = 11;
469
                LED_ON = PD7_L;
469
                LED_ON = PD7_L;
470
                LED_OFF = PD7_H;
470
                LED_OFF = PD7_H;
471
        }
471
        }
472
       
472
       
473
       
473
       
474
        // output again
474
        // output again
475
        if (!old_PORTD7) PORTD &= ~(1 << PD7); // PD7 disable pullup (LED)
475
        if (!old_PORTD7) PORTD &= ~(1 << PD7); // PD7 disable pullup (LED)
476
        if (old_DDRD7) DDRD |= (1 << PD7); // PD7 output (LED)
476
        if (old_DDRD7) DDRD |= (1 << PD7); // PD7 output (LED)
477
}
477
}
478
 
478
 
479
 
479
 
480
/**
480
/**
481
 * call for help whenever needed
481
 * call for help whenever needed
482
 */
482
 */
483
void help(uint8_t load) {
483
void help(uint8_t load) {
484
    uart_puts_pgm(PSTR("\r\nC-STROM\r\n\tBUILD: "));
484
    uart_puts_pgm(PSTR("\r\nC-STROM\r\n\tBUILD: "));
485
        uart_puts_pgm(PSTR(BUILDDATE));
485
        uart_puts_pgm(PSTR(BUILDDATE));
486
        uart_puts("\r\n\tHW: ");
486
        uart_puts("\r\n\tHW: ");
487
        uart_puts(itoa_dec(hwver, s));
487
        uart_puts(itoa_dec(hwver, s));
488
 
488
 
489
        uart_puts("\r\n");
489
        uart_puts("\r\n");
490
 
490
 
491
        if (load) get_eeprom();
491
        if (load) get_eeprom();
492
       
492
       
493
        uart_puts_pgm(PSTR("\tSensor: "));
493
        uart_puts_pgm(PSTR("\tSensor: "));
494
        uart_puts(itoa(sensor, s, 10));
494
        uart_puts(itoa(sensor, s, 10));
495
        uart_puts_pgm(PSTR("A\tCalibration: "));
495
        uart_puts_pgm(PSTR("A\tCalibration: "));
496
        uart_puts(itoa(cal_ampere, s, 10));
496
        uart_puts(itoa(cal_ampere, s, 10));
497
 
497
 
498
        uart_puts_pgm(PSTR("\r\n\tTWI is "));
498
        uart_puts_pgm(PSTR("\r\n\tTWI is "));
499
        if (CSTROM_CONFIG & CSTROM_TWI) {
499
        if (CSTROM_CONFIG & CSTROM_TWI) {
500
                uart_puts_pgm(PSTR("ON, SPI may not work!!!"));
500
                uart_puts_pgm(PSTR("ON, SPI may not work!!!"));
501
        } else {
501
        } else {
502
                uart_puts_pgm(PSTR("OFF"));
502
                uart_puts_pgm(PSTR("OFF"));
503
        }
503
        }
504
 
504
 
505
 
505
 
506
        uart_puts_pgm(PSTR("\r\n\tPIMARY R2: "));
506
        uart_puts_pgm(PSTR("\r\n\tPIMARY R2: "));
507
        uart_puts(itoa_dec(prim_r2, s));
507
        uart_puts(itoa_dec(prim_r2, s));
508
        if (hwver == 11) {
508
        if (hwver == 11) {
509
                uart_puts_pgm(PSTR("kOhm"));
509
                uart_puts_pgm(PSTR("kOhm"));
510
                uart_puts_pgm(PSTR("\tANIN R2: "));
510
                uart_puts_pgm(PSTR("\tANIN R2: "));
511
                uart_puts(itoa_dec(anin_r2, s));
511
                uart_puts(itoa_dec(anin_r2, s));
512
        }
512
        }
513
        uart_puts_pgm(PSTR("kOhm\r\n"));
513
        uart_puts_pgm(PSTR("kOhm\r\n"));
514
 
514
 
515
        uart_puts_pgm(PSTR("\tCommands available:\r\n"));
515
        uart_puts_pgm(PSTR("\tCommands available:\r\n"));
516
        uart_puts_pgm(PSTR("\t\th : help on commands (this)\r\n"));
516
        uart_puts_pgm(PSTR("\t\th : help on commands (this)\r\n"));
517
        uart_puts_pgm(PSTR("\t\tc : calibrate ampere\r\n"));
517
        uart_puts_pgm(PSTR("\t\tc : calibrate ampere\r\n"));
518
        uart_puts_pgm(PSTR("\t\tT : toggle TWI (may break SPI communication!)\r\n"));
518
        uart_puts_pgm(PSTR("\t\tT : toggle TWI (may break SPI communication!)\r\n"));
519
        uart_puts_pgm(PSTR("\t\t+/- : to change sensor\r\n"));
519
        uart_puts_pgm(PSTR("\t\t+/- : to change sensor\r\n"));
520
        uart_puts_pgm(PSTR("\t\tr/f : to change PRIMARY-R2 Value\r\n"));
520
        uart_puts_pgm(PSTR("\t\tr/f : to change PRIMARY-R2 Value\r\n"));
521
        if (hwver == 11) {
521
        if (hwver == 11) {
522
                uart_puts_pgm(PSTR("\t\te/d : to change ANIN-R2 Value\r\n"));
522
                uart_puts_pgm(PSTR("\t\te/d : to change ANIN-R2 Value\r\n"));
523
        }
523
        }
524
        uart_puts_pgm(PSTR("\t\ts : save values\r\n"));
524
        uart_puts_pgm(PSTR("\t\ts : save values\r\n"));
525
        uart_puts_pgm(PSTR("\tnow enjoy it and have fun...\r\n\r\n"));
525
        uart_puts_pgm(PSTR("\tnow enjoy it and have fun...\r\n\r\n"));
526
}
526
}
527
 
527
 
528
 
528
 
529
/**
529
/**
530
 * Main
530
 * Main
531
 */
531
 */
532
int main (void) {
532
int main (void) {
533
        DDRD |= (1 << PD7); // PD7 output (LED)
533
        DDRD |= (1 << PD7); // PD7 output (LED)
534
 
534
 
535
        check_hw();
535
        check_hw();
536
        uart_init();
536
        uart_init();
537
       
537
       
538
        Init_Slave_IntContr();
538
        Init_Slave_IntContr();
539
        init_timer0();
539
        init_timer0();
540
 
540
 
541
        sei();   // Enable Global Interrupts
541
        sei();   // Enable Global Interrupts
542
 
542
 
543
    uart_puts("\x1B[2J\x1B[H"); // clear serial
543
    uart_puts("\x1B[2J\x1B[H"); // clear serial
544
 
544
 
545
        help(1);
545
        help(1);
546
 
546
 
547
        if (CSTROM_CONFIG & CSTROM_TWI) init_twi_slave(CSTROM_I2C);
547
        if (CSTROM_CONFIG & CSTROM_TWI) init_twi_slave(CSTROM_I2C);
548
 
548
 
549
        int16_t raw_volt = 0, raw_ampere = 0, raw_aninvolt = 0;
549
        int16_t raw_volt = 0, raw_ampere = 0, raw_aninvolt = 0;
550
        char c[10] = "         ";
550
        char c[10] = "         ";
551
        c[9] = 0;
551
        c[9] = 0;
552
 
552
 
553
        //strom_data  = *((SPI_strom_data_t*) &spi_buffer);
553
        //strom_data  = *((SPI_strom_data_t*) &spi_buffer);
554
        //*spi_buffer = *((uint8_t*) (void*) &strom_data);
554
        //*spi_buffer = *((uint8_t*) (void*) &strom_data);
555
 
555
 
556
        LED_ON();
556
        LED_ON();
557
 
557
 
558
        while (1) { // Loop Forever
558
        while (1) { // Loop Forever
559
 
559
 
560
                // we have got a normal voltage measuring circuit that takes the lipo-voltage
560
                // we have got a normal voltage measuring circuit that takes the lipo-voltage
561
                raw_volt = readADC(1);
561
                raw_volt = readADC(1);
562
                /* according to what i read about voltage divider it is
562
                /* according to what i read about voltage divider it is
563
                   Uo = Ue * (R1 / (R2 + R1))
563
                   Uo = Ue * (R1 / (R2 + R1))
564
                   Ue = Uo * (R2 + R1) / R1
564
                   Ue = Uo * (R2 + R1) / R1
565
                   the board has got r1 = 4.7k and r2 = 15k
565
                   the board has got r1 = 4.7k and r2 = 15k
566
                   but since 1step is 0,0048828125V = 4,8828125mV and not 5mV there
566
                   but since 1step is 0,0048828125V = 4,8828125mV and not 5mV there
567
                   is some conversion to do for raw_volt --**-> Uo
567
                   is some conversion to do for raw_volt --**-> Uo
568
                   this should end up in 10th of volts */
568
                   this should end up in 10th of volts */
569
                raw_volt = ((uint32_t)raw_volt * (uint32_t)48828) / (uint32_t)10000;
569
                raw_volt = ((uint32_t)raw_volt * (uint32_t)48828) / (uint32_t)10000;
570
                volt = (int16_t) (((uint32_t)raw_volt * (uint32_t)(prim_r1 + prim_r2)) / (uint32_t)prim_r1) / 100;
570
                volt = (int16_t) (((uint32_t)raw_volt * (uint32_t)(prim_r1 + prim_r2)) / (uint32_t)prim_r1) / 100;
571
                if (volt < 0) volt = 0;
571
                if (volt < 0) volt = 0;
572
 
572
 
573
                // and we have got a seccond voltage measuring circuit for user voltages
573
                // and we have got a seccond voltage measuring circuit for user voltages
574
                raw_aninvolt = readADC(2);
574
                raw_aninvolt = readADC(2);
575
                /* some conversion to do for raw_volt --**-> Uo
575
                /* some conversion to do for raw_volt --**-> Uo
576
                   this should end up in 10th of volts */
576
                   this should end up in 10th of volts */
577
                raw_aninvolt = ((uint32_t)raw_aninvolt * (uint32_t)48828) / (uint32_t)10000;
577
                raw_aninvolt = ((uint32_t)raw_aninvolt * (uint32_t)48828) / (uint32_t)10000;
578
                anin_volt = (int16_t) (((uint32_t)raw_aninvolt * (uint32_t)(anin_r1 + anin_r2)) / (uint32_t)anin_r1) / 100;
578
                anin_volt = (int16_t) (((uint32_t)raw_aninvolt * (uint32_t)(anin_r1 + anin_r2)) / (uint32_t)anin_r1) / 100;
579
                if (anin_volt < 0) anin_volt = 0;
579
                if (anin_volt < 0) anin_volt = 0;
580
 
580
 
581
                raw_ampere = readADC(0);
581
                raw_ampere = readADC(0);
582
                /* according to datasheet sensitivity is nominal 40mV per A for the 50A chip
582
                /* according to datasheet sensitivity is nominal 40mV per A for the 50A chip
583
                   this would mean 50A ^= 2V since 0A is set to 2.5V output Voltage we get
583
                   this would mean 50A ^= 2V since 0A is set to 2.5V output Voltage we get
584
                   a range of 0.5V till 4.5V for the full range.
584
                   a range of 0.5V till 4.5V for the full range.
585
                   the atmega ADC features 0...5V range divided into 10bit ^= 1024 steps
585
                   the atmega ADC features 0...5V range divided into 10bit ^= 1024 steps
586
                   so 0,0048828125V, or 4,8828125mV, is one step
586
                   so 0,0048828125V, or 4,8828125mV, is one step
587
                   this leads us to 0,8192 steps per 0,1A and somehow the below formula
587
                   this leads us to 0,8192 steps per 0,1A and somehow the below formula
588
                   and i know that 32bit is evil, but what else does this device has to do? :)
588
                   and i know that 32bit is evil, but what else does this device has to do? :)
589
                   this should end up in 100th of ampere */
589
                   this should end up in 100th of ampere */
590
                ampere = (int16_t) (((int32_t)(((int16_t)raw_ampere - (int16_t)cal_ampere)) * (int32_t)10000) / (int32_t) 819);
590
                ampere = (int16_t) (((int32_t)(((int16_t)raw_ampere - (int16_t)cal_ampere)) * (int32_t)10000) / (int32_t) 819);
591
                if (sensor == 100) ampere *= 2;
591
                if (sensor == 100) ampere *= 2;
592
 
592
 
593
                if ((CSTROM_FLAGS & CSTROM_WRITEUART)) {
593
                if ((CSTROM_FLAGS & CSTROM_WRITEUART)) {
594
                        uart_puts("V: ");
594
                        uart_puts("V: ");
595
                        uart_puts(itoa_dec(volt, s));
595
                        uart_puts(itoa_dec(volt, s));
596
                        write_space(10-strlen(s));
596
                        write_space(10-strlen(s));
597
 
597
 
598
                        uart_puts("AN-IN V: ");
598
                        uart_puts("AN-IN V: ");
599
                        uart_puts(itoa_dec(anin_volt, s));
599
                        uart_puts(itoa_dec(anin_volt, s));
600
                        write_space(10-strlen(s));
600
                        write_space(10-strlen(s));
601
 
601
 
602
                        uart_puts("A: ");
602
                        uart_puts("A: ");
603
                        uart_puts(itoa(ampere, s, 10));
603
                        uart_puts(itoa(ampere, s, 10));
604
                        write_space(10-strlen(s));
604
                        write_space(10-strlen(s));
605
 
605
 
606
                        uart_puts("C: ");
606
                        uart_puts("C: ");
607
                        uart_puts(itoa(mah, s, 10));
607
                        uart_puts(itoa(mah, s, 10));
608
                        write_space(10-strlen(s));
608
                        write_space(10-strlen(s));
609
                       
609
                       
610
                        uart_puts("\r");
610
                        uart_puts("\r");
611
                        CSTROM_FLAGS &= ~CSTROM_WRITEUART;
611
                        CSTROM_FLAGS &= ~CSTROM_WRITEUART;
612
                }
612
                }
613
 
613
 
614
                //spi_buff
614
                //spi_buff
615
                if (!(CSTROM_FLAGS & CSTROM_SPILOCKED)) {
615
                if (!(CSTROM_FLAGS & CSTROM_SPILOCKED)) {
616
                        // TESTTING 
616
                        // TESTTING 
617
                        if (!(CSTROM_CONFIG & CSTROM_TWI)) CSTROM_FLAGS |= CSTROM_SPILOCKED;
617
                        if (!(CSTROM_CONFIG & CSTROM_TWI)) CSTROM_FLAGS |= CSTROM_SPILOCKED;
618
                        SPI_buffer.data.ampere = ampere;
618
                        SPI_buffer.data.ampere = ampere;
619
                        SPI_buffer.data.mah = mah;
619
                        SPI_buffer.data.mah = mah;
620
                        if (hwver == 11) {
620
                        if (hwver == 11) {
621
                                SPI_buffer.data.volt = anin_volt;
621
                                SPI_buffer.data.volt = anin_volt;
622
                        } else {
622
                        } else {
623
                                SPI_buffer.data.volt = volt;
623
                                SPI_buffer.data.volt = volt;
624
                        }
624
                        }
625
                }
625
                }
626
        }
626
        }
627
   return 0;
627
   return 0;
628
}
628
}
629
 
629