Thank you very much for the reply. I’ve gone through your check list and believe I have addressed each point.
I have a bench supply I’m using for the +5V input (I put in 5.2)…ample current available.
The input light is lit so polarity is correct.
I’ve initialized the ADCSRA register to 0 which should disable ADC.
I tested the outputs of the optoisolators as a proxy for what’s going to the AVR. If there was no input, the optoisolator outputs were high. If there was a high input, the output of the optoisolator was low.
My code below is commented related to the results I would get based on how PORTA was initialized. It seems no matter how I initialize port A and despite I have the DDRA set for input, the inputs never reflect what’s coming into them.
Perhaps this is a code issue or perhaps this is a hardware issue, I don’t know. Here’s the code I’m using to test the functionality - if you see something wrong, please let me know.
Thanks,
Landon
/* avriom16.c
*
* code to drive the Olimex AVR-IO-M16 relay dev board
*
* this functionality will accept commands from the serial
* port and also tie any of the 4 port inputs to their corresponding
* outputs so if the input goes high, the relay will fire.
*
* this way the device can be driven either through GPIO from a micro
* or wireless comm device like XBee or LANtronix, or through a direct
* connection to a serial device or terminal.
*
* Copyright (C) 2007, 360VL, Inc. All rights reserved
* Copyright (C) 2007, Landon Cox. All rights reserved
*
* This code is licensed per Apache 2.0 open source licensing.
*/
#include <avr/io.h>
#include <stdio.h>
#include <string.h>
#include "bits.h"
// AVR-IO-M16 related defines - derived from the Olimex schematic
#define LEDPORT PORTD
#define LED (1<<PD7)
#define RELAYPORT PORTB
#define RELAY1 (1<<PB3)
#define RELAY2 (1<<PB2)
#define RELAY3 (1<<PB1)
#define RELAY4 (1<<PB0)
#define IN1PORT PORTD
#define IN1 (1<<PD2)
#define IN2PORT PORTA
#define IN2 (1<<PA0)
#define IN3PORT PORTA
#define IN3 (1<<PA1)
#define IN4PORT PORTA
#define IN4 (1<<PA2)
// not sure what the fastest baud rate is for AVR mega16 running at 16MHz
// but this works and is fast enough for what we need to do...occasionally flip a relay switch
#define BAUD_RATE 38400ul
// #define FOSC 1000000UL
// #define FOSC 8000000UL
#define UBBR_VAL ((FOSC/16/BAUD_RATE)-1)
// FOSC is now override defined in makefile
// FOSC of 8000000UL (8 MHz) which is the max of the ATMega8 Olimex AVR-P28 board assumes
// the fuse bits as follows:
//
// CKOPT 1
// CKSEL3 1
// CKSEL2 1
// CKSEL1 1
// CKSEL0 1
// SUT1 1
// SUT0 0
//
// In AVR fuse parlance, a bit value of 1 is "unprogrammed" and a bit value of 0 is "programmed".
// In PonyProg fuse checkbox dialog, an unprogrammed
// those fuse bits will cause the crystal oscillator to be used as the clock source
// so, FOSC must match whatever you use for clock source.
//
// default ATMega8 settings are:
// CKOPT 1
// CKSEL3 0
// CKSEL2 0
// CKSEL1 0
// CKSEL0 1
// SUT1 1
// SUT0 0
//
// These will use the 1MHz internal oscillator as clock source, if you just plug in a raw
// ATMega8, these will be the settings and FOSC in the Makefile should be 1000000 (1MHz)
void init()
{
// Input/Output Ports initialization
// Port B
RELAYPORT = 0x00;
DDRB=0x0F; // O1-4 are on PB3-PB0 respectively
// Port C
PORTC=0x00;
DDRC=0x20;
// Port D
PORTD=0x00;
DDRD=LED; // IN1 is on port D but is input, so nothing to do on the DDRD for it
// LED is tied to +5V opposite. avr pin side would be gnd, so take it low
LEDPORT &= ~LED;
// test - this should fire all 4 relay ports and turn their LEDs on in the process
// RELAYPORT |= 0x0f; // send them all high
// test fire 1 relay - this succeeds, no problems
RELAYPORT |= RELAY1;
// baud rate set
UBRRH = (uint8_t)(UBBR_VAL >> 8 );
UBRRL = (uint8_t)(UBBR_VAL);
UCSRB = (1<<RXEN)|(1<<TXEN);
// to access UCSRC which shares the same i/o location as UBRRH, the URSEL bit must
// be set, otherwise it will update UBRRH instead
// URSEL - must be 1 to write to UCSRC
// UMSEL - 0 asynchronous - 1 synchronous
// USBS - 0 1 stop bit, 1, 2 stop bits
// UPM1 UPM0 - 10 - even parity, 11, odd parity, 00 disabled (no parity)
// UCSZ2 UCSZ1 UCSZ0 - 011 (8 bits), 010 (7bits)
UCSRC = (1<<URSEL)|
(0<<UMSEL)|
(0<<USBS)|
(1<<UCSZ1)|(1<<UCSZ0);
}
void sendbyte( uint8_t databyte )
{
// if byte is being transmitted, wait for that
while((UCSRA&(1<<UDRE)) == 0);
UDR = databyte;
}
uint8_t getbyte()
{
// wait until a byte is received
while( (UCSRA&(1<<RXC)) == 0);
return UDR;
}
void sendStr( char *str )
{
while ( *str != '\0' )
{
sendbyte( (uint8_t)*str++);
}
}
int main(void)
{
init();
sendStr("test AVR IO driver v1.0\r\n");
while( 1 )
{
// read the inputs and match the relays with the input states
unsigned char porta;
char output[80];
// PORT A
ADCSRA = 0x00; // disable ADC
// PORTA=(IN2 | IN3 | IN4); // if I set these states, later, PORTA will be read all high, even when input is low
PORTA=0x00; // if I set these states on PORTA, later, it will be read all low, even when the input is high
DDRA=0x00; // all input for now
porta = PORTA;
sprintf( output, "porta: %0x\n", porta );
sendStr( output ); // no matter what is input through the terminals, this is always 0
// I also injected 5v into pa7 and pa6 directly but I still only get 0
// these reflect what is read from Port A - if PORTA is initialized 0x00, regardless of input terminal input, all are low
// if PORTA is initialized (IN2|IN3|IN4), then regardless of input terminal input, all are high
uint8_t in1, in2, in3, in4;
in1 = IN1PORT & IN1;
in2 = IN2PORT & IN2;
in3 = IN3PORT & IN3;
in4 = IN4PORT & IN4;
if ( in1 > 0 )
RELAYPORT |= RELAY1;
else
RELAYPORT &= ~RELAY1;
if ( in2 > 0 )
RELAYPORT |= RELAY2;
else
RELAYPORT &= ~RELAY2;
if ( in3 > 0 )
RELAYPORT |= RELAY3;
else
RELAYPORT &= ~RELAY3;
if ( in4 > 0 )
RELAYPORT |= RELAY4;
else
RELAYPORT &= ~RELAY4;
if ( (in1 | in2 | in3 | in4) > 0 )
{
sprintf(output,"in1: %08x in2: %08x in3: %08x in4: %08x\n", in1, in2, in3, in4);
sendStr( output );
}
else
{
sprintf(output,"in1: %08x in2: %08x in3: %08x in4: %08x\n", in1, in2, in3, in4);
sendStr( output );
}
}
/* disable serial input until I get an interrupt driven serial library running
uint8_t databyte;
sendStr("start - type a character and the next character in sequence will be echoed back to you ");
while( 1 )
{
databyte = getbyte();
sendbyte( databyte + 1 );
}
*/
}
void relay( int num, int value )
{
// todo convenience function
}