[Edit - moderator - moved to appropriate forum]
I'm using atmega8 and L293D. when i give input to the atmega, i don't get any output. below is my code. i'm just learning how to code, so i don't know if its perfect.
inputs d0-forward, d1-reverse, d2-turn left, d3-turn right.
outputs b6 In1 and In4,b7 In2 and In3,d5 enable left of H bridge,d6 enable right of H bridge
void forward()
{
PORTD = 0b01100000;
PORTB = 0b01000000;
}
void reverse()
{
PORTD = 0b01100000;
PORTB = 0b10000000;
}
int main()
{
DDRD = 0b01100000;
DDRB = 0b11000000;
PORTB = 0b00000000;
PORTD = 0b00000000;
while(1)
{
if(PORTD == 0b00000001) // move forward
forward();
else if(PORTD == 0b00000010) // reverse
reverse();
else if(PORTD == 0b00000101) // turn left forward
{
forward();
_delay_ms(100);
PORTD = 0b01000000;
PORTB = 0b01000000;
_delay_ms(100);
}
else if(PORTD == 0b00001001) // turn right forward
{
forward();
_delay_ms(100);
PORTD = 0b00100000;
PORTB = 0b01000000;
_delay_ms(100);
}
}
return 0;
}
not getting output
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- stinkbutt
- Posts: 593
- Joined: Wed Feb 17, 2010 2:40 am
Re: not getting output
OK, first of all, I'm going to assume you're using avr-gcc here. Which I think you are, but it's not impossible this is just butchered Arduino code. But if it's avr-gcc code, I see a few places you could be getting tripped up:
1. Double check to see if you're getting your pins correct. Are you perhaps thinking that DDRB = 0b11000000 is setting the first two pins to output and the last 6 to input? In binary I think you're setting the LAST two pins to output, but I can't be certain since I don't know where these input pins actually are on the device. I'm just saying make sure you've got that bit right. It's an easy mistake to make.
2. Don't use PORTx for input. It's there for OUTPUT, and checking the PORTx values for pins that are configured for input isn't doing what you think it's doing. It's instead mucking about with the internal pull-up resistors. Setting DDRx to 0 (input) and PORTx to 1 turns on an internal pull-up resistor:
So really all you're testing there is what the current pull-up values for the internal resistors are. NOT what you care about, huh?
3. For input use PINx. There's a third variable available to you, called PINB or PIND which is what you should be using for reading values.
4. We're not done yet. Your if/then tests are all messed up. You DON'T want to ever test the entire value of the PINB variable. You don't necessarily know what your program has been doing to muck about with the values of the output pins and more importantly you don't care. Instead of the code:
You want to do this:
Note I've made two changes to your code. First I used PIND instead of PORTD. Second this bit here:
(PIND & 0b00000001)
That bit does a bitwise AND operation. Because the first bit is 1 and the rest are 0, then the last 7 bits of the output will ALWAYS be zero. And the first bit will be a if the value of pin D0 is 1, and 0 if it's 0. Then I can use comparison properly.
Anyway, try making those changes. Also, you really shouldn't be using 0b00000001 and such for your variables all over the place. Strictly speaking it's accurate, but it's ugly as all hell. There are better options:
Instead of 0b00000001 you could use the bitshift operator and write:
1<<0
That shifts the number 1 down zero bits. Which isn't impressive, but look at where that's going:
0b00000001 == 1<<0
0b00000010 == 1<<1
0b00000100 == 1<<2
0b00001000 == 1<<3
Now let's say you want to make 0b00000101? You just use a bitwise OR:
0b00000101 == (1<<0) | (1<<2)
Even better, you can use the _BV() macro, which does exactly the same thing with slightly more readable code:
1<<0 == _BV(0)
1<<1 == _BV(1)
etc. etc. etc...
Finally, you can use the global constants available in avr-gcc so you don't worry as much about what the exact position of the pin is. For example to set DDRB you could write this code:
Note the operator: |=
That does an OR operation on the item to the left with the item to the right and ASSIGNS it to the item on the left. It's like += and *=, if you've ever seen those.
If you insist on using avr-gcc to compile code for ATMegas (a bad idea, IMO, for new programmers - Arduino's got a much less imposing learning curve) then you're going to need to get up to speed on bitwise operations lickety-split. GL
1. Double check to see if you're getting your pins correct. Are you perhaps thinking that DDRB = 0b11000000 is setting the first two pins to output and the last 6 to input? In binary I think you're setting the LAST two pins to output, but I can't be certain since I don't know where these input pins actually are on the device. I'm just saying make sure you've got that bit right. It's an easy mistake to make.
2. Don't use PORTx for input. It's there for OUTPUT, and checking the PORTx values for pins that are configured for input isn't doing what you think it's doing. It's instead mucking about with the internal pull-up resistors. Setting DDRx to 0 (input) and PORTx to 1 turns on an internal pull-up resistor:
So really all you're testing there is what the current pull-up values for the internal resistors are. NOT what you care about, huh?
3. For input use PINx. There's a third variable available to you, called PINB or PIND which is what you should be using for reading values.
4. We're not done yet. Your if/then tests are all messed up. You DON'T want to ever test the entire value of the PINB variable. You don't necessarily know what your program has been doing to muck about with the values of the output pins and more importantly you don't care. Instead of the code:
Code: Select all
if(PORTD == 0b00000001) // move forward
forward();
Code: Select all
if( (PIND & 0b00000001) == 0b00000001 ) // Just testing bit zero
forward();
(PIND & 0b00000001)
That bit does a bitwise AND operation. Because the first bit is 1 and the rest are 0, then the last 7 bits of the output will ALWAYS be zero. And the first bit will be a if the value of pin D0 is 1, and 0 if it's 0. Then I can use comparison properly.
Anyway, try making those changes. Also, you really shouldn't be using 0b00000001 and such for your variables all over the place. Strictly speaking it's accurate, but it's ugly as all hell. There are better options:
Instead of 0b00000001 you could use the bitshift operator and write:
1<<0
That shifts the number 1 down zero bits. Which isn't impressive, but look at where that's going:
0b00000001 == 1<<0
0b00000010 == 1<<1
0b00000100 == 1<<2
0b00001000 == 1<<3
Now let's say you want to make 0b00000101? You just use a bitwise OR:
0b00000101 == (1<<0) | (1<<2)
Even better, you can use the _BV() macro, which does exactly the same thing with slightly more readable code:
1<<0 == _BV(0)
1<<1 == _BV(1)
etc. etc. etc...
Finally, you can use the global constants available in avr-gcc so you don't worry as much about what the exact position of the pin is. For example to set DDRB you could write this code:
Code: Select all
DDRB = 0; // Sets all 8 registers to zero. Probably not necessary, but included for clarity.
DDRB |= _BV(PB6) // Sets PB6 high for output
DDRB |= _BV(PB7) // Sets PB7 high for output
That does an OR operation on the item to the left with the item to the right and ASSIGNS it to the item on the left. It's like += and *=, if you've ever seen those.
If you insist on using avr-gcc to compile code for ATMegas (a bad idea, IMO, for new programmers - Arduino's got a much less imposing learning curve) then you're going to need to get up to speed on bitwise operations lickety-split. GL
Please be positive and constructive with your questions and comments.