[328p] motor control + sensor

Hi,
I have some troubles programming my 328p. I’m not so good with programming, so here is my question.
I modified the example that comes with pololu lib. When the object is close to the sensor, one of the motor slows down and another stops, so the robot could make a turn. When there is no obstacle, two motors go full speed. It works, but I want to make the robot stop and when the value I get from the sensor is less than, for example 50 and backup until that value riches 70. Basically I don’t understand why my if statements don’t work.
for examlpe:

if (avg <50)
{ 
set_m2_speed (0);
set_m1_speed (0);
delay
set_m2_speed (-40);
set_m1_speed (-40);
}

here is the code:

#include <pololu/orangutan.h>

unsigned int sum;
unsigned int avg;
unsigned char samples;

int main()
{
  set_analog_mode(MODE_8_BIT);    // 8-bit analog-to-digital conversions
  sum = 0;
  PORTC=0x00;
  samples = 0;
  avg = 0;
  start_analog_conversion(PORTC=0x00);  // start initial conversion

  
   while(1)
  {
    if (!analog_is_converting())     // if conversion is done...
    {
      sum += analog_conversion_result();  // get result
      start_analog_conversion(PORTC=0x00);          // and start next conversion
      if (++samples == 20)
      {
	avg = sum / 20;             
	samples = 0;
	sum = 0;
      }
    }
			set_m2_speed (80);
			set_m1_speed (80);
     		       delay_us(256- avg);
			set_m2_speed (30);
			set_m1_speed (0);
			delay_us(avg+1);
	

	}
}

thanks.

Hello.

The code you posted is just our analog example with LED code replaced by motor code. The point of the LED code was to have the LED flicker at a rate proportional to the analog reading, which is accomplished by rapidly turning it on and off. You can’t just put “set_motor” functions in place of the “red_led” functions and expect anything useful to happen. Did you consider using one of the motor example programs as a starting point?

You say you don’t understand why your “if” statements don’t work, but your actual code doesn’t have any if statements other than those used to obtain the analog readings. You haven’t provided any specifics about what isn’t working and how it’s failing. How do you expect us to help you?

- Ben

yes, I tried motor1 example and it didn’t work for me for the first time, and I just tried it again and was able to make it work with my sensor readings instead of pot. So, I guess I’m all set for now…
One more question:
I don’t have LCD and it would be really helpful if I could see what the value I’m getting from the sensor in real time.(or any other variable) Should I use hyper terminal or there is an easy way?

thanks again

The easiest way would probably be to use a USB-to-TTL-serial adapter to connect to a computer and to use a terminal program to receive/send data from your MCU. The Pololu AVR library has routines for sending and receiving serial data.

- Ben

I’m using this combination pololu.com/catalog/product/1302 (usb avr programmer)

seems like there is no easy way to print the value of avg from the example below:

#include <pololu/orangutan.h>

unsigned long prevMillis = 0;
unsigned int sum;
unsigned int avg;
unsigned char samples;

int main()
{
 
  set_analog_mode(MODE_8_BIT);  
  sum = 0;
  PORTC=0x00;
  samples = 0;
  avg = 0;
  start_analog_conversion(PORTC=0x00); 
  
  while(1)
  {
   if (!analog_is_converting())     
    {
      sum += analog_conversion_result();  
      start_analog_conversion(PORTC=0x00);         
      if (++samples == 20)
      {
        avg = sum / 20;             
        samples = 0;
        sum = 0;
      }
    }

    int motorSpeed = (145-avg)/2;  
    set_motors(motorSpeed, motorSpeed);
    }
 
}

I guess I need to use serial_receive function, but I couldn’t find any examples…

Hello,

The function serial_send sends data from the AVR to whatever it is attached to; in your case you could receive it on the computer. We don’t provide any particular helper functions for converting numbers into printable format, but here is some easy, untested code:

serial_set_baud_rate(9600);
char *buffer[5]; // large enough to hold the string "65535"
unsigned char i;
for(i=0;i<5;i++)
{
  buffer[4-i] = avg % 10; // put the digits in the correct order
  avg /= 10;
}
serial_send_blocking(buffer, 5);

Does the integer math make sense to you? Please take a look at the library documentation and make sure you understand what the code is doing, how to connect it to your USB-to-serial converter, and so on - and ask us for help if you have more questions.

-Paul

i understand the code, but is it supposed to output something by itself or I need to write a “print” command or send request through the terminal? anyway, I gave up already and bought LCD. I connected it according to lv-168 schematic, but for some reason only second string is showing black squares and lcd example doesn’t work.

should I ground pins 15 and 16?
I don’t use switches for 11-13, is it ok?
I can change the brightness using trimpot.

1 gnd
2 +5V
3 trimpot
4 PD2
5 PB0 + 4.7K to pin 10
6 PD4
7 gnd
8 gnd
9 gnd
10 gnd 
11 PB1
12 PB4
13 PB5
14 PD7 + led
15 not connected
16 not  connected

thanks

[size=150]update
lcd works perfectly fine. I was flashing the wrong hex file :slight_smile: [/size]

Well, it’s great that you got it working with the LCD. Anyway, the code I posted was just an example - it will just send the number stored in ‘avg’ to the serial port when you run it. Whether you make it part of a more complicated program or not is completely up to you.

-Paul

unfortunately I don’t have enough time for the experiments, may be in the nearest future I try using terminal again.

I’m confused…
I need to read sensor values from PC5 and PC4. Here is how I do that:

int main()
{
set_analog_mode(MODE_8_BIT); 
DDRC&=~((1<<PORTC5)|(1<<PORTC4));

 avg = sensor();  
 avg2 = sensor2();

some code...
}

int sensor()
{
   start_analog_conversion(PORTC5);
   while (analog_is_converting()){}
   return(analog_conversion_result()<<1);
}   


int sensor2()
{
   start_analog_conversion(PORTC4);
   while (analog_is_converting()){}
   return(analog_conversion_result()<<1);
}   

values of avg and avg2 are equal… why?

The code you posted looks like it should work, unless I am missing something. It is not a good idea to use the PORTC4 macro as an argument to the start_analog_conversion() function, since that function expects the number of the analog channel, a different concept from the number of a bit on port C. However, PORTC4 is equal to 4, so it should work.

Anyway, can you give me some more information? If the two numbers are always exactly equal, but you are getting some response from your sensors, then you should be able to tell me which sensor value you are getting. Also, can you replace the second sensor reading line with

avg2 = sensor2() + 10;

and verify that you see avg2 always exactly equal to avg + 10?

Also, why are you not using our built-in function analog_read(), which does exactly what you are doing?

-Paul

yes, in that case avg2 = sensor1 +10

because analog example in pololu library that I used doesn’t use built-in functions.
i just did this:

   avg=analog_read_average(5,10);
   avg2=analog_read_average(4,10);

seems like it works.

not sure where should I post it…

I built flame detection circuit and an alarm circuit. Now I need to activate alarm when the flame is detected. I know how to do it using transistors, but I need some more control…

here is how I’m thinking to do it:

if (avg2>90) // flame  detected
DDRC&=~(1<<PORTC3);
else
DDRC|=(1<<PORTC3);

I then connect alarm to PC3 using transistor as a switch that will trigger alarm on or off. Is it the right way to do what I need?