Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PWM input to AVR

Status
Not open for further replies.

MrMikey83

New Member
I have purchased a JR 5 channel dual stick radio control. The output for the reciever is PWM. Is there a website I can go to that explains how to read the PWM signal on an ATMEGA32 port?
~Mike
 
The modual that is usually used to read PWM is called a Capture-Compare module. It lets you run a timer and latch the timer value automaticaly when an input edge is received. Check the datasheet on your AVR and see if it has one of these modules - also check the timers and PWM modules because they sometime can be run in a Capture-Compare mode.
 
OK, the Atmega32 has a compare mode for each of its three timer/counters.
I need to be able to input 5 PWM signals though.

What I want to do...

if PWMin is high
then read timer value

when PWMin goes low, read timer value
subtract fist reading from second and get time of high pulse

Does this sound like it should work? If so, do you know how I would code this in C? I have the code writen, but I dont know what command I need to use to read the timer value.
~Mike
 
Actually you need to run the timer in capture mode. You should be able to set which edge captures the timer value. Both the timer and capture value can be read from their special registers. The data sheet will tell you which registers you need to read to get these values.

The C code is just like using a variable. Atmel should have a special header file for your controller that gives nice names for the register locations.
 
So..theres no way to use normal input PINS to bring in my PWM signals?

If not, then my best course of action would be to have maybe at ATtiny12 or other small AVR on each PWm input, then have those talk to the main AVR through the ADC with a 0 to 5 voltage I guess?
 
MrMikey83 said:
So..theres no way to use normal input PINS to bring in my PWM signals?

Yes, it's very simple - just use a software loop to measure the incoming pulse width - PIC BASIC and STAMP's even have a command for doing exactly that.

There's a free online book at https://www.dontronics.com/see.html which gives assembler details of most STAMP commands (including this one).
 
Which command is that Nigel? I took a look at the site, but unless I missed something, only found PWM out info.
~Mike
 
MrMikey83 said:
Which command is that Nigel? I took a look at the site, but unless I missed something, only found PWM out info.
~Mike

The one's just above PWM, PulsIn and PulsOut, the two commands used for reading and writing servo pulses (or any pulses?).
 
This morning, I found out that the PWM signal from my radio receiver is only going up to about .7 volts. Is this correct? Do i need to pull it up to 5 volts?
~Mike
 
MrMikey83 said:
This morning, I found out that the PWM signal from my radio receiver is only going up to about .7 volts. Is this correct? Do i need to pull it up to 5 volts?
~Mike

I've no idea what the interface signal looks like?, perhaps it's an open collector output with pullup resistors in the servos?. Have you tried connecting a servo to it and testing it then?.

BTW, refering to it as PWM is likely to cause confusion, although it is a pulse with it's width modulated it's not what is usually called PWM. PWM usually has a far greater range, and is used for power control, motors etc.
This is perhaps why you've been looking at PWM modules, which aren't usually suitable for servo control?.
 
OK, I didn't know that.
The receiver came with 4 servos and they all work when connected. The servos are NES 537 if that helps.

My meter can read Pulse width and the output ranges from about 1mS to 2mS.
 
MrMikey83 said:
My meter can read Pulse width and the output ranges from about 1mS to 2mS.

Yes, the range of a servo is roughly 1-2mS, with 1.5mS (obviously) in the middle. As already mentioned by someone else, the repetition rate is about 20mS - although this is VERY uncritical.
 
Nigel, So do you think the signal from the receiver is like a PWM where the entire pulse is the same each time except the high is shortened or lengthened...or does it just change frequency all together?

I tried Timer0 instead of Timer1 and finally was able to get the timer running, but when I use it in my code, I dont get anything.

PWMin is where I have the receiver connected. timeUP, timeDOWN and pulse are variables. The printf lines are for me to see what is hapenning when I run it. The Terminal output looks like this...
|13|0|0|
|128|0|0|
|231|0|0|
|19|0|0|
|132|0|0|
|251|0|0|
...

The first number is the timer. The second is my "pulse" output. The third is to monitor the overflow. As you can see, the "pulse" code didn't work, but also, the overflow isn't counting up either. I have an overflow interupt which increments the variable ov_counter.


Code:
while (1)
      {
            
            if(PWMin == 1)
            {
                  timeUP = TCNT0;
            }
            else
            {
                  timeDOWN = TCNT0;
            }
            pulse = (timeDOWN - timeUP) / 500;
            
            printf("|%d|", TCNT0);
            printf("%d|", pulse);
            printf("%d|", ov_counter);
            putchar(13);
            delay_ms(300);
      };
}
 
MrMikey83 said:
Nigel, So do you think the signal from the receiver is like a PWM where the entire pulse is the same each time except the high is shortened or lengthened...or does it just change frequency all together?

The signal from the transmitter is a series of pulses between 1mS and 2mS, these are repeated every 20mS.

On the receiver side you have a number of output channels (one for each pulse), each channel outputs a single 1-2mS pulse every 20mS or so.

The width of the 1-2mS pulse varies with the controls on the transmitter, the 20mS should probably stay the same - but there's no guarantee it will, and there's no need to - the only information is on the width of the positive going pulse.

To read more than one pulse with a micro you have to make sure you read them in the right order, the pulses appear on the outputs in the sequential order they were transmitted. If you don't, you might be waiting up to 20mS between individual pulse readings, rather than a potential maximum of less than 20mS for all of them. If you get it wrong the readings will appear slow and sluggish.
 
OK, so what do you think is wrong with my code above thats making it not work?
~Mike
 
Your code isn't quite right

Code:
while(1)
{
   while (PWMin = 0) {}   /* wait for input to go high*/
   timeUPStart = TCNT0;        /* capture the time when the signal when high*/
   while (PWMin = 1) {}  /* wait for the signal to go low*/
   timeUPEnd = TCNT0;  /* capture when the pulse goes low*/
   Pulse = timeUPEnd - timeUPStart;  /*be careful deviding this so you don't end up with 0: 250 / 500 = 0 in integer math*/
}

This code isn't tested but this is the basic idea.
 
bmcculla,
you forgot to put double equals signs in the while string andf the code after the while's isn't within the brackets. I fixed those problems, renamed some things and I am getting an output signal. I dont have any idea what I was doing wrong the first time around, but I understand how yours works and I will be able to get a good signal from it. And since I can use normal inputs, I will be able to read all 5 channels of the radio controller.
Thanks a million man!
~Mike
 
Sorry about the syntax - I'm switching back and forth between a couple languages right now so I'm a little confused.

The problem with your code is that it didn't wait for the signal to go from high to low and back. It prints each time you poll the input. Printfs are really slow - Printing one character at 9600 baud takes ariound 1ms so all the prints in your code probably took 25ms or so - enough time to screw up your measurements. You needed to only print after the high to low transition. You should avoid any prints in time critical code.
 
It wont be printing anything when the code is done and installed in the robot.
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top