Balancing robot code help

Hi, I am trying to make a simple 2 wheels balancing robot.

Relevant materials:
1x Baby Orangutan B328 (implements control PI)
1x MX2125 (accelerometer) http://www.parallax.com/dl/docs/prod/compshop/SICMemsicTut.pdf

Idea:
Pulse width from MX2125 represents acceleration component so Baby Orangutan B328 measures it (received in PD0) and set motors speed according to it.
Since I am new working with AVR, I based my work on the examples provided in libpololu-avr (libpololu-avr/examples/atmega328p/pulsein1 and pulsin2).

Problem:
Problem is that these examples codes and my own (based on them doesn’t) seem to work with Baby Orangutan B328. I modified the code posted to make motors work just by detecting a new high pulse… but nothing. A friend tried the code directly from examples in a 3pi (by changing the library to the 3pi) and it worked perfectly.

Is there a problem with my code?, are these examples not compatible with Baby Orangutan B328? By the way, MX2125 generates pulses with a constant period of 10ms… is this too fast for Baby Orangutan B328 pulses processing capacity?

My code:

#include <pololu/orangutan.h>

// This array of pins is used to initialize the OrangutanPulseIn routines.  
const unsigned char pulseInPins[] = { IO_D0 };


int main()
{
	set_digital_input(IO_D0, PULL_UP_ENABLED);	// enable internal pull-up on PD0
	pulse_in_start(pulseInPins, 1);		// start measuring pulses on PD0

	while (1)  // main loop
	{
		if (new_high_pulse(0))	// if we have new high pulse
		{
set_motors (100,100);
		}

    }
}

By detecting a new pulse, motors should start working… but they don’t.

Thanks for any help you can provide me :wink: .

Hello.

Your code generally looks ok, but the many commented lines of code are distracting. Can you post the code your friend used successfully? How are you generating your input pulse when testing your code? The Baby Orangutan can measure pulses on the order of microseconds, so 10 ms is definitely not too fast.

- Ben

The input pulse is being generated by the MX2125 (5v amplitude with a period of 10ms) by connecting its pin 2 to a resistance (220 ohm) to Baby Orangutan B328 pin PD0.
---------
He applied almost exactly in a 3pi the code from the example pulsein2. He is also using MX2125 to generate the pulse. I tried the same code in a Baby Orangutan, but of course by changing the library and deleting the display parts and inicio.

My goal was to make the motors start working once they receive a pulse… but no. Applied to 3pi the code works perfectly

#include <pololu/3pi.h>  

const unsigned char pulseInPins[] = { IO_C5 };


void inicio()
{
	while(!button_is_pressed(BUTTON_B))  
    {  
        clear();  // clear LCD
        print_long(read_battery_millivolts());  
        print("mV");  
        lcd_goto_xy(0,1);
        print("Pulsa B");  
        delay_ms(100);  
    }

    
    wait_for_button_release(BUTTON_B);  
    
    clear();   
  }
int main()
{
	inicio();

	pulse_in_start(pulseInPins, 1);		// start measuring pulses on PC5

	while (1)  // main loop
	{
		unsigned long curPulse;		// length of current pulse in ticks (0.4 us)
		unsigned char state;		// current state of input (1 if high, 0 if low)
		// get current pulse state for D0
		get_current_pulse_state(0, &curPulse, &state);	// pass arguments as pointers

		// if more than 300 ms have elapsed since the last pin
		// change on this channel, we indicate that pulses have stopped
		if (pulse_to_microseconds(curPulse) >= 300000UL)
		{
			if (state == HIGH)		// if line is currently high
			{
				lcd_goto_xy(0, 0);	// go to start of first LCD row
				print("Pin HIGH  ");
				lcd_goto_xy(0, 1);	// go to start of second LCD row
				print("          ");	// clear the row by overwriting with spaces
			}
			else
			{
				lcd_goto_xy(0, 0);	// go to start of first LCD row
				print("          ");	// clear the row by overwriting with spaces
				lcd_goto_xy(0, 1);	// go to start of second LCD row
				print("Pin  LOW  ");
			}
		}
		else if (new_high_pulse(0) && new_low_pulse(0))	// if we have new high and low pulses
		{
set_motors(100,100);
			unsigned long high_pulse = get_last_high_pulse(0);
			unsigned long period_in_ticks = high_pulse + get_last_low_pulse(0);

			// compute frequency as 1 / period = 1 / (0.4us * period_in_ticks)
			//  = 2.5 MHz / period_in_ticks
			unsigned long frequency_in_hz = 2500000UL / period_in_ticks;

			// duty cycle = high pulse / (high pulse + low pulse)
			// we multiply by 100 to convert it into a percentage and we add half of the denominator to
			// the numerator to get a properly rounded result
			unsigned long duty_cycle_percent = (100 * high_pulse + period_in_ticks/2) / period_in_ticks;

			lcd_goto_xy(0, 0);		// go to start of first LCD row
			print_unsigned_long(frequency_in_hz);		// print the measured PWM frequency
			print(" Hz      ");
			lcd_goto_xy(0, 1);		// go to start of second LCD row
			print("DC: ");
			print_unsigned_long(duty_cycle_percent);	// print the measured PWM duty cycle
			print("%  ");
		}
	}
}

Thanks

The Baby Orangutan has the same microcontroller as the 3pi, so the code that works for your friend should also work for you (except for routines corresponding to hardware you don’t have, like the buzzer or LCD).

In general, I’m concerned that there could be more fundamental problems than your program, such as bad electrical connections (is the Baby Orangutan actually getting a pulse from your sensor?) or insufficient power (is the Baby Orangutan resetting when you try to drive the motors?).

I suggest you simplify things by eliminating the sensor and motors from the system for now and just try to get the pulse detection working. For example, please try the following (untested) code:

#include <pololu/orangutan.h>
const unsigned char pulseInPins[] = { IO_D0 };

int main()
{
   set_digital_input(IO_D0, PULL_UP_ENABLED);   // enable internal pull-up on PD0
   pulse_in_start(pulseInPins, 1);      // start measuring pulses on PD0

   while (1)  // main loop
   {
      if (new_high_pulse(0))   // if we have new high pulse
      {
        red_led(HIGH);
        delay_ms(100);
        red_led(LOW);
      }

    }
}

While the program is running, tap on pin PD0 with a grounded wire. If you see the red user LED flash when you do this, you know that you are detecting pulses. If you don’t get any response from the red LED, I suggest you simplify the program even further to just monitor the digital input value of pin PD0 and light the LED when it is low. Depending on what works and what doesn’t, we will have a much better idea of where the problem might be.

Please let me know what happens!

- Ben

The Baby Orangutan is receiving the pulse (using oscilloscope). But power as you pointed may be the problem, I was using one 6v battery (or 4 AAA battery arrangement (4.8v)) for the complete system (baby, 2x motors and sensor).

By the way I am replacing Baby Orangutan with a Orangutan SV-328. I had a problem with the board… (I exceeded drivers current capacity :cry: ). At least code stays the same…

Thanks for your code, your point is really good. I will try this simplified version and report what happens.

Your four-cell arrangement in particular is worrying because the nominal voltage is already below the Baby Orangutan’s 5 V minimum. It’s very possible that the brief current spike from turning both motors on dropped the input voltage below the Baby Orangutan’s brown-out voltage, thereby resetting the microcontroller. In general, I don’t recommend using motors for program feedback because it is difficult to tell if your problems are software-related or power-related.

I’m sorry to hear you damaged your Baby Orangutan. Can you tell me more about what happened? Please note that the Orangutan SV-328 has the same motor drivers as the Baby Orangutan, so you might consider going with the Orangutan SVP instead if you need more power for your motors.

- Ben

You were right the voltage was the problem. I tried my codes using just 1 motor and the sensor. The motor unlike the previous attempts was the item #1099. All the variants worked as desired (with some minor corrections).

About my Baby Orangutan B-328, well I was originally testing a speed variant code (backward/forward with speed set at 200) with 2x #1442. Since motors barely reacted (sometimes they didn’t did a thing at all) I replaced batteries with a voltage generator… which of course provided all the current they needed (near 5A I guess…) frying my baby in the process :cry:

Sadly for my project I do need those #1442, but due to particular reasons getting an Orangutan SVP isn’t an option. So I wonder if this new subject was consulted before:

Is there any suggested arrangement I could use to feed a couple of #1442 with an Orangutan SV-328(directly or indirectly (as an enabler))?

Thanks for all your help so far

You will need external drivers to control those motors with an Orangutan SV, which seems like a bit of a waste since the SVP and Orangutan X2 are like an SV with the stronger drivers built-in. Is using a motor controller or motor driver an option?

By the way, have you considered using one of our accelerometers? They’re much less expensive than the Parallax accelerometers, and because they output analog voltages, they are generally easier to use.

- Ben

Sadly getting them isnt an option for me (time is a limiting)…I will try to work with what I can get on the period of time at my disposal. I am thinking on using solid state reles to feed motors, by controling their states with Orangutan PWM signal…

Funny thing is that I do have Pololu accelerometers, but due to a bad advice I decided working with a different sensor. Anyway my work seems to be working well with it.

Thanks for all your help
By the power of Greyskull I declare this topic closed