BabyO 328p help reading digital input in IO

I am starting a project with the BabyO and admittedly have only used code sections of other programs.

I have the motor code working fine using the example from the resources tab, and have tried to incorporate code from the OrangutanProject1, but I am sure I am missing something obvious. Basically I want to read the output from a ProxDot IR detector which has a single high/low digital output easy to interface with most microcontrollers - Digital output goes “low” when an object is in range - These will be connected to PC0 and PC2

I tried to modify the code based on the commented sections in the OrangutanProject1, but I must have missed something obvious as I get no response from the motors. Here is what I have:

#include <avr/io.h>

// Motor Control Functions -- pwm is an 8-bit value
//  (i.e. ranges from 0 to 255)

void M1_forward(unsigned char pwm)
{
  OCR0A = 0;
  OCR0B = pwm;
}

void M1_reverse(unsigned char pwm)
{
  OCR0B = 0;
  OCR0A = pwm;
}

void M2_forward(unsigned char pwm)
{
  OCR2A = 0;
  OCR2B = pwm;
}

void M2_reverse(unsigned char pwm)
{
  OCR2B = 0;
  OCR2A = pwm;
}

// Motor Initialization routine -- this function must be called
//  before you use any of the above functions
void motors_init()
{
    // configure for inverted PWM output on motor control pins:
    //  set OCxx on compare match, clear on timer overflow
    //  Timer0 and Timer2 count up from 0 to 255
    TCCR0A = TCCR2A = 0xF3;

    // use the system clock/8 (=2.5 MHz) as the timer clock
    TCCR0B = TCCR2B = 0x02;

    // initialize all PWMs to 0% duty cycle (braking)
    OCR0A = OCR0B = OCR2A = OCR2B = 0;

    // set PWM pins as digital outputs (the PWM signals will not
    // appear on the lines if they are digital inputs)
    DDRD |= (1 << PORTD3) | (1 << PORTD5) | (1 << PORTD6);
    DDRB |= (1 << PORTB3);
}

#define F_CPU 8000000  // system clock is 20 MHz
#include <util/delay.h>  // uses F_CPU to achieve us and ms delays



// delay for time_ms milliseconds by looping
//  time_ms is a two-byte value that can range from 0 - 65535
//  a value of 65535 (0xFF) produces an infinite delay
void delay_ms(unsigned int time_ms)
{
    // _delay_ms() comes from <util/delay.h> and can only
    //  delay for a max of around 13 ms when the system
    //  clock is 20 MHz, so we define our own longer delay
    //  routine based on _delay_ms()

    unsigned int i;

    for (i = 0; i < time_ms; i++)
        _delay_ms(1);        
}



int main()
{
// Pin Assignments for ProxDots


	DDRC  &= ~(1 << PORTC2);	// make pin PC2 an input
	PORTC |=  (1 << PORTC2);	// enable pull-up on pin PC2 (this means pin PC2
							//  will read as high unless externally driven low)

while (1)
{


if (PINC & (1 << PORTC2))	// if pin PC2 input reads as high, RUN MOTORS
  	{
		M1_forward(125);  
    	M2_forward(125);							
    }   	
else  // stop motors
	{
		M1_forward(0);  // Stopped
    	M2_forward(0);  // Stopped     

	}
} //close while

} //close main

I will be using PC0 AND PC2, but am just testing the functionality with PC2.

Any thoughts are appreciated.

Thanks,
Mike

Your code looks very nice, but it doesn’t look like you’re actually calling the motor initialization function in main.

-Adam

Well that is what I get for cutting and pasting too many times. I looked at this 10 times and never saw it. Thanks for the correction. Now to add dual sensors for left/right and your battery monitoring code from an earlier post.

thanks!

Mike

Hello.

You also might consider trying the Pololu AVR library, which provides motor-control functions and might help simplify your code.

- Ben

OK - i will check that out as well.

I have one more follow-up question. According to the comments in the code from the OrangutanProject1 on the website, PORTC2 will read high unless it is driven low. My documentation for the IR detector says " Digital output goes “low” when an object is in range" My understanding is that I would have no response from the sensor unless an object is detected however the REVERSE is true. The motors run when no object is detected and stop when there is an object.

DDRC  &= ~(1 << PORTC2);	// make pin PC2 an input
PORTC |=  (1 << PORTC2);	// enable pull-up on pin PC2 (this means pin PC2
					//  will read as high unless externally driven low)

The problem is here - I think:
if (PINC & (1 << PORTC2)) // if pin PC2 input reads as high

This is taken from other code, but I am not sure how to change it to read when it is LOW and if there is a better way to write this - I am all ears. I have tried inverting it with an !, but no luck. I will eventually be using PORTC0 and a switch statement, but this notation is a bit different than other examples I have used.

Thanks for any comments!

Mike

A ‘!’ should work in this case, so long as you’re logically inverting the entire argument rather than just one part of it. Wrapping the entire argument in parenthesis and !-ing it should do:

if (!(PINC & (1 << PORTC2))) // if pin PC2 input reads low

-Adam

Thanks - I had not negated the entire statement. Is there a cleaner way to state this?

Yes and no. AVR Libc has some old (deprecated?) macros for checking the state of bits in a register directly, but I find its better to force yourself to understand the steps that are going on, so things aren’t even more confusing later.

-Adam

Very valid point - thanks for the feedback.