PWM with old Baby

Hi, I bought a Baby Orangutan a while ago, but never used it. Now I have a project that I can use it on. I’m trying to get the motor controller to control two small motors. This board has the Mega48 and LB1836M chips on it. I’ve downloaded the “orangutan-lib” files which seem to be made around the time that this board was current. I’ve looked at the “pwm.c” file to see how they do the motor control logic and it seems that they are using the PWM module in a way that they are controlling the pins directly through software interrupts and not through the PWM hardware. Was there any reason they did this this way?? The PWM modual is used as a counter and when there is a match it goes to an interrupt and sets whatever bits to make the motor run.

The reason I’ve looked at this code is that when I try to code it my self, one motors runs at the speeds I need (controlled by the ADC7 pot on-board) and motor two on starts up (at full speed) when then pot is at full speed.

This is my code (after trying to fix it several times):

// Initialize the timer to do interrupt-based PWM for our motors:
void Init_PWM(void)
{
    // set PWM pins as digital outputs (the PWM signals will not   
    // appear on the lines if they are digital inputs)   
    DDRD |= (1 << PD5) | (1 << PD6);
    DDRB |= (1 << PB1) | (1 << PB2);

	// Fast PWM 8-Bit
	// Set the Timer Control Register to set a clock prescale of 256
	TCCR1A = 0xC1; 
	TCCR1B = 0x0C;
	TCCR1C = 0x00;

    // initialize all PWMs to 0% duty cycle (braking)   
	OCR1A = 1;
	OCR1B = 1;
	clearBit( PORTD, 5 );
	clearBit( PORTD, 6 );
}

void setM1Speed( int speed )
{
	int nspd;

	if ( speed > 255 )
		speed = 255;
	if ( speed < -255 )
		speed = -255;


	if ( speed > 0 ) //Forwards
	{
		OCR1A = speed;
		clearBit( PORTD, 5 );
	}
	else if ( speed < 0 ) //Reverse
	{
		nspd = speed + 255;
		
		OCR1A = speed;
		setBit( PORTD, 5 );
	}
	else //Stop
	{
		OCR1A = 0;
		setBit( PORTD, 5 );
	}
}

What’s the right way to do it and why?

Denis

Hello.

The original Baby Orangutan uses interrupts to achieve variable motor speed because the motor driver inputs are not all connected to hardware PWM outputs. Long story condensed into a single sentence: the original Baby Orangutan was based on the original Orangutan, which initially used the ATmega8, which only has one eight-bit timer, which meant that there wasn’t really a good way to allow for purely hardware-driven motor control. One improvement we made on the Baby Orangutan B was to take advantage of the ATmega48/168/328’s two eight-bit timers by using their four hardware PWM outputs as motor driver inputs, so variable motor speed can be achieved entirely in hardware once the proper registers are set.

Before I look more closely at your code, is there a reason why you’re not just using the motor control routines directly from Orangutan-lib?

- Ben

Hi thanks for the quick reply. I wanted to find a wAy to use the hardware pwm. I had a new b168 that I accidently killed and it was working through hardware pwm. When I look at the schematic for the old b48 it is using pb1 and pd5 for motor 1 and pb2 and pd6 for motor2. On the mega 48 those are all conected to hardware pwm right? Ocr0 (pb1-2) and ocr1 (pd5-6). What motor controller pins are not connected to the hardware?

[Edit]:
I see now why I can’t use OCR1 (PD5-6) because the two timers won’t be synced together. but I should still be able to use OCR0 for motor speed and PD5-6 for direction right? That’s what I’m doing in my code shown above, but I can’t get it to work.

It looks like I was mistaken about the hardware PWM outputs on the original Baby Orangutan. The hardware outputs of timers 0 and 1 are connected to the four motor driver inputs, but they’re connected in a way that makes them hard to use since timer 0 is an eight-bit timer and timer 1 is a sixteen-bit timer.

Basically, for each motor driver channel, one input is a timer 0 PWM output and one input is a timer 1 PWM output. When you want to drive at a variable speed, you should ground one input (i.e. turn off the PWM output and make the line a digital output driven low) and enable the PWM output on the other motor driver input at the desired duty cycle. To drive the motor in the other direction, flip what you’re doing with the inputs. Note that you can create an 8-bit PWM with timer 1 by setting the TOP value to 255, and it’s even possible to synchronize timers 0 and 1 (see the ATmega48 datasheet for more information), but synchronizing is only important if you want to do variable braking.

Also note that pins PD5 and PD6 are timer 0 PWM outputs (not timer 1 outputs as you seem to indicate in your post), and pins PB1 and PB2 are timer 1 PWM outputs.

Basically, I recommend you get out the datasheet and use it to understand how you’re configuring timer 1 (e.g. what is the TOP value of the PWM, is it normal or inverted, etc). Use that along with the motor driver datasheet truth table to see what effect the driver inputs will have on the motor driver outputs. If you keep having trouble, I’ll take a closer look at your code to see exactly what effects your timer register values are having. One potential problem I notice, however, is that you are setting OCR1A (an unsigned integer) equal to a negative value in the reverse case, which is almost certainly not what you want to do (you initialize nspd to a non-negative value, but you never use it).

- Ben

Ok, thanks, I’ll try that.

In the code I gave:

   else if ( speed < 0 ) //Reverse
   {
      nspd = speed + 255;
      
      OCR1A = speed;
      setBit( PORTD, 5 );
   }

OCR1A should be equal to nspd which makes speed positive and make use of nspd. In the test I did, I wasn’t using the reverse speeds so I don’t think this was causing any problems.

Please let us know how it works out.

- Ben

I tried out what you said and it didn’t work. I understand how the motor driver works with the logic table. I can get Motor1 to work, but Motor2 only works when I turn the pot all the way up (CW).

I tried the orangutan-lib code and it works and I think I’ll just stick to that.

Thanks,
Denis.