sodjan skrev:Du säger ingenting om hur det hela är kopplat.
Det finns inte så mycket att säga. Enklast möjliga, µC, max3232 på ena kortet och 202 på andra, till serieport.
mri: Jovisst, det kan jag hålla med om, och jag säger inget om att problemen är orelaterade. Förslag på vad jag bör kolla?
Edit: mri, stängde av timer2 OVF-interruptet vilket fick rätt på detta. Får felsöka det senare.
Nu återigen, sänder ett 0xAA från AVRen och får 0xD5 i datorn.
sodjan: 11010101, dvs D5 sänds från µC när jag tittar i skopet.
Edit2:
Nu blir jag bestört. Sedan jag stängde av interruptet har visserligen inte den första byten jag sänder blivit rätt, men efterföljande trafik är ok. Detta till trots har det hela tiden fungerat i simulatorn.
Det är kanske på sin plats att posta all kod:
Kod: Markera allt
#include "avr/io.h"
#include "avr/interrupt.h"
#include "stdlib.h"
#include "stdio.h"
#include "avr/eeprom.h"
#include "util/delay.h"
#include "math.h"
#define tempchan 2
#define poschan 6
#define negchan 7
#define CMP 0b00100000
#define CST 0b00001000
#define WMP 0b00010000
unsigned char k_type;
unsigned char sinpos = 0;
signed int EHAcomp; /*How much EHA is compensated */
unsigned int EHAinpos; /* EHA input, positive */
unsigned int EHAinneg; /* EHA input, negative */
signed int EHAinact; /* EHA actual input, diff between pos/neg */
unsigned char EHAshould; /* What value EHAact should have */
signed int EHAout;
unsigned char sercount = 14; //
unsigned char out_a;
unsigned char out_b;
/*
ADC6 - EHA in 1
ADC7 - EHA in 2
ADC2 - LM335 in
PC0.1 - EHA ground transistors
INT0 - Sense pwr off
OC2B - Q3(X3-2)
PD4 - OK2 (remember to pull up internally)
OC0B - ana out, X3-4
OC0A - ana out, X3-3
PD7 - KE3-jumper (remember to pull up internally)
OC1A - Q1(X3-6)
OC1B - Q2(X3-5)
*/
/*
* sends string on uart
*/
void uart_sendstring(char *str)
{
int i;
for(i = 0; str[i] != 0; i++) {
while(!(UCSR0A & _BV(UDRE0)));
UDR0 = str[i];
}
while(!(UCSR0A & _BV(UDRE0)));
UDR0 = 4;
}
unsigned int adcread(unsigned char chan)
{
unsigned char t;
unsigned int result;
/* selects channel, as well as voltage reference */
ADMUX = (0b01000000 | chan);
/* Start ADC conversion */
ADCSRA |= 0b01000000;
/* waits for conversion to be done */
while(ADCSRA&0b01000000);
result = (ADCH<<8 | ADCL);
/* workaround for reading ADCH last */
t = ADCH;
return result;
}
unsigned int gettemp(void)
{
unsigned int t;
/* unsigned int i; */
t = adcread(tempchan);
/* workaround for reading ADCH last */
/* i = ADCH; */
/* some shit to convert the read value to temperature */
t *= 25;
t >>= 1;
t *= 5;
t >>= 7;
return t;
}
unsigned char getcoldduty(void) {
unsigned char d;
unsigned int t = gettemp();
/* Ninja magic for a reasonable relation
between temp and CS valve duty% */
signed int c = (5*(313-t));
if(c < 1) {
d = 0;
}
if(c > 254) {
d = 255;
}
if((c < 255) && (c > 0)) {
d = c;
}
return d;
}
void setup(void)
{
DDRD = 0b01101010;
PORTD = 0b10010100;
DDRC = 0b00111011;
DDRB = 0b00000111;
TCCR0A = 0b10100011; /* fast PWM, set at TOP, clear on match */
TCCR0B = 0b00000001; /* prescaler at 0 */
TCCR1A = 0b10100001; /* fast PWM, set at TOP, cleat on match */
TCCR1B = 0b00001100; /* prescaler at 256, TCCR2A = 0b00100011;
fast PWM, set at TOP, clear on match,
not OC2A */
TCCR2B = 0b00000001; /* Prescaler at 1024 */
//TIMSK2 = 0b00000001; /* tim2 ovf interrupt enable, 14Hz. */
UCSR0A = 0b00000000;
UCSR0B = 0b00011000; /* Receiver transmitter enabled, RXC interrupt disabled */
UCSR0C = 0b00000110; /* 8 bits */
UBRR0L = 23; /* 19k2 at 3686400Hz */
ADMUX = 0b01000000; /* AVCC as ref, ADC channel 0 */
ADCSRA = 0b10000111; /* ADC enabled, CLK/128 prescaler */
ADCSRB = 0b00000000; /* Auto trigger is off */
DIDR0 = 0b00000100; /* Disables digital input of ADC2 */
EICRA = 0b00000011; /* Rising edge of INT0 generates interrupt */
EIMSK = 0b00000001; /* Enables INT0 */
/* determines if KE3 jumper is in place */
if(PIND & 0b10000000) {
k_type = 3;
} else {
k_type = 0;
}
//EHAcomp = eeprom_read_word((uint16_t*)12);
sei();
}
/*
* calculates the actual compensation for EHA value and outputs to DA
* converter. OCR0A is positive output, OCR0B is negative output
*/
void regulate_lambda(void) {
unsigned char t;
/* these two lines output cold start duty% on CS valve. */
OCR2B = getcoldduty();
/* this determines the supposed value of EHA signal,
depending on KE or KE3. */
if(PIND & 0b10000000)
EHAshould = 41;
else
EHAshould = 0;
EHAinpos = adcread(poschan);
EHAinneg = adcread(negchan);
EHAinact = (EHAinpos - EHAinneg);
if(!OCR2B){ /*Only regulate if no cold start is taking place */
/* 12 gives a tolerance of about 3mA before an action is taken. */
if(EHAinact > (EHAshould + 12) && (EHAcomp < 127)) {
EHAcomp++;
}
/* this is where the actual regulation is */
if(EHAinact < (EHAshould - 12) && (EHAcomp > -127)) {
EHAcomp--;
}
}
/* if output is within range of 8b, go ahead. */
if((EHAcomp + EHAinact) > -255 && ((EHAcomp + EHAinact)) < 255) {
EHAout = (EHAcomp + EHAinact);
}
/* if output is above range of 8b */
if((EHAcomp + EHAinact) > 255) {
EHAout = 254;
}
/* if output is below range of 8b */
if((EHAcomp + EHAinact) < -255) {
EHAout = -254;
}
/* if output is positive and within range */
if(EHAout > 0 && EHAout < 255) {
out_a = EHAout;
out_b = 0;
}
/* if output is positive and below range */
if(EHAout < 0 && EHAout > -255) {
/* make output positive and output to PWM */
t = (EHAout - (2*EHAout));
out_b = t;
out_a = 0;
}
/* pos=OC0B, neg=OC0A, controls output transistors */
if(out_a > out_b) {
PORTC &= 0b11111101;
PORTC |= 0b00000001;
OCR0A = out_a;
OCR0B = out_b;
}
if(out_b > out_a) {
PORTC &= 0b11111110;
PORTC |= 0b00000010;
OCR0A = out_a;
OCR0B = out_b;
}
/*
if((EHAcomp + EHAinact) > 0 && ((EHAcomp + EHAinact) < 255)) {
OCR0B = 0;
OCR0A = (EHAcomp + EHAinact);
}
if((EHAcomp + EHAinact) < 0 && ((EHAcomp + EHAinact) > -255)) {
t = (EHAcomp + EHAinact);
t &= 0b01111111;
OCR0B = t;
OCR0A = 0;
}
*/
}
ISR(INT0_vect) /* shutdown procedure, EHAcomp must be saved in eeprom */
{
cli();
OCR0B = 0;
OCR0A = 0;
OCR2B = 0;
eeprom_write_word((uint16_t*)12,EHAcomp);
UDR0 = 'k';
unsigned int d = 0xffff;
while(PIND&0b00000100);
while(d) d--;
setup();
}
void usart_recv()
{
char str[12];
char byte;
PORTB |= 0b00000001;
byte = UDR0;
if(byte == 0xf0) UDR0 = 4;
if(byte == 0xf1){
sprintf(str, "Comp %.3d", EHAcomp);
uart_sendstring(str);
}
if(byte == 0xf2){
sprintf(str, "In act %.3d", EHAinact);
uart_sendstring(str);
}
if(byte == 0xf3){
sprintf(str, "Temp %.3d", (gettemp() - 273));
uart_sendstring(str);
}
if(byte == 0xf4){
sprintf(str, "CSV %.3d", OCR2B);
uart_sendstring(str);
}
if(byte == 0xf5){
sprintf(str, "Out act");
uart_sendstring(str);
}
}
ISR(TIMER2_OVF_vect)
{
//cli();
regulate_lambda();
PORTB |= 0b00000100;
//UDR0 = '0';
sei();
}
int main(void)
{
PORTB |= WMP;
UDR0 = 0xaa;
setup();
sei();
while(1) {
/* if(PORTB & 0b00000001) {
PORTB &= 0b11111110;
}
else {
PORTB |= 0b00000001;
}*/
if(UCSR0A & 0b10000000){
PORTB |= CST;
usart_recv();
}
}
}