![]() |
Need help with PWM 1-2ms pulse control
Hey everyone,
How do I make my analog control the PWM outputs? I have a sliding pot that I wil be using, and I want the pwm to pulse 1.5ms in neutral when the slider is near the middle, all the way up for 255 and bottom with a 0. Anywhere in between becomes variable speed. Im new to programming, so any help would be awesome. I just want to be able to make my servo adjust to my analog input. Much like a RC transmitter and receiver. P.S. I am using the old smaller IFI Mini robot controller. |
Re: Need help with PWM 1-2ms pulse control
The old EDU robot controller has analog inputs with values from 0 to 1023.
The pwm outputs are sent values from 0 to 254. So just scale the input to match the output like so Code:
pwm01 = (long) Get_Analog_Value(rc_ana_in01) * 254 / 1023; |
Re: Need help with PWM 1-2ms pulse control
Quote:
Code:
pwm01 = (char) (((long) Get_Analog_Value(rc_ana_in01)) * 254L / 1023L); |
Re: Need help with PWM 1-2ms pulse control
Sorry about that :ahh:
I corrected my post, but took the simplest route to make the calculation happen as a long. Implied typecasts occur for the other parts. Explicit typecasting all around is safer though. Thanks! |
Re: Need help with PWM 1-2ms pulse control
Quote:
Code:
pwm01 = Get_Analog_Value(rc_ana_in01)/4; |
Re: Need help with PWM 1-2ms pulse control
Quote:
|
Re: Need help with PWM 1-2ms pulse control
Um...im getting an analog value from 0 - 22. or 0-23, is this right? I thought it was supposed to be from 0 to 254?
|
Re: Need help with PWM 1-2ms pulse control
Quote:
The direct analog inputs on the EDU controller have 10-bit resolution, so you should see 0-1023 returned as values. If you are talking about the analog input from a radio transmitter joystick, then that value is indeed 0-254. How exactly are you printf-ing the value? There may be a simple error there. At least that's where I'd check first. I assume it looks something similar to: Code:
printf("Analog input = %d\r\n", (int) Get_Analog_Value(rc_ana_in01)); |
Re: Need help with PWM 1-2ms pulse control
What's the range of resistance of the pot?
|
Re: Need help with PWM 1-2ms pulse control
I did mine like this:
printf("Analog In = %d\n", Get_Analog_Value(rc_ana_in01)); But thats right though, the readings im getting are still 0-22. could it be that I've got the pot hooked up wrong? I have it connected to ground and signal. Its a 10k pot, and I tested it on the multimeter. Could it be something in the user_initialization? Im using the EDU Default code right now to debug this problem. Set_Number_of_Analog_Channels(TWO_ANALOG); |
Re: Need help with PWM 1-2ms pulse control
1 Attachment(s)
Here's how the analog should be hooked up, so that's one problem.
This is from the IFI EDU guide: http://www.ifirobotics.com/docs/lega...2004-mar-1.pdf Pots are hooked up the way you have yours on the FRC Operator Interface, but not on the robot controller, so it can be confusing. P.S. Minor notes: I believe the 2004 EDU version of printf expected signed ints as inputs. Get_Analog_Value is defined as an unsigned int, so as a matter of principle I'd typecast it when printing it, however, with such a low value you won't see any difference. Felix is refering to the fact that the EDU analog inputs are optimized for 100k pots, but while using a 10k pot would affect your full range somewhat, you shouldn't really notice. |
Re: Need help with PWM 1-2ms pulse control
Yeap, I have it done correctly, With the analog input, the signal pin is always logic high, and all I did was plug in a var pot from ground to the signal pin. Is as if you plugged in a solid resistor in its place.
Im sure its done right, as I have used this pot on other robots. So what could be the problem? Is it maybe because Im using V7.5 MPLAB? Could that be it? I tried 7.2 but it wouldnt open any projects. |
Re: Need help with PWM 1-2ms pulse control
Well. Forget about that, I dont know why, but im leaving it as:
pwm01 = (long) Get_Analog_Value(rc_ana_in01) * 254 / 22; This actually works out to 0 being full reverse, and 254 being full forward, and 127 bing neutral. My analog inputs read 0 - 22 for some reason. Thats the easy part, heres the harder part. What do I need to do to make the PWM outputs respond like this: ![]() So set A and Set B represents the PWM values, it can be either one as a result of a simple switch. And according to the adjustments on the pot, the speed on the servo varies in equal magnitude in either direction. If the pot is moved towards the top, The servo can be spining real fast depending on the switch. if the pot is near the bottom but not dead bottom. The servos can spin slowly in either direction, again, depending on the switch. Has anyone attemped this before? Im totally clueless to where to start with this. |
Re: Need help with PWM 1-2ms pulse control
Normally the signal pin measures power coming in from the +5v power pin not flowing out to ground. (Taking Ben Franklin's view of electricity)
As long as you understand that your description of how you wired the pot is incorrect for normal operation, but you're happy with it then there's no problem. You've just wired it as a voltage divider that's all. I just don't want anyone else reading this to get the wrong idea though. If you want only the seven specific values in Set A or B then you'd use a lookup table or nested If statements. If you want variable speeds then just map 0-22 to the corresponding range of pwm values, e.g., 0-22 mapped to 0-127 for Set B. For a lookup table, you create an array with one entry for each of the possible 23 values that your pot could be. Then you pull values from the array using the analog input as an index. Code:
static unsigned int pwm_setB[23]={0,0,0,25,25,25,47,47,47,64,64,64,80,80,80,100,100,100,127,127,127};Code:
unsigned int value; |
Re: Need help with PWM 1-2ms pulse control
Quote:
|
Re: Need help with PWM 1-2ms pulse control
Alright...I've resoldered the pot now, and its working nicely.
....now into the problem with the casting Set A and Set B. Im not sure what you mean by casting 0 - 126 to Set A and casting 127 - 254 to Set B. Do you mean that When the switch is set to A side, it will only activate PWM pulses between 0 - 126? and the same with side B ( 127-254)? How should I seperate the pulses into two groups? Ive only been able to get 1 side of it working. I doubled the numerical value of the pot and that gave me the ability to control PWM pulses between 0 - 127. So it would look something like this: Before pwm01 = (long) Get_Analog_Value(rc_ana_in01) * 254 / 1024; After pwm01 = (long) Get_Analog_Value(rc_ana_in01) * 254 / 2048; Im stumped. Sorry for all these questions, Im not a programmer, but I need to figure this out, so any help is much appreciated. |
Re: Need help with PWM 1-2ms pulse control
on the software side, heres my take.
I read that you want to map the analog pot directly to the pwm out right, so heres what I'd do: pwm01 = Get_Analog_Value(rc_ana_in01) >> 2; Now for the question on having two "sets". Assuming you are getting full 10 bits range now and you want two sets char set = 1; // set to 0 for the other set, or hook a switch up to this variable. if(set == 1) { // 127 to 254 pwm01 = (Get_Analog_Value(rc_ana_in01) >> 3) + 127; } else { // 127 to 0 pwm01 = 127 - (Get_Analog_Value(rc_ana_in01) >> 3); } maybe you need to add some casting above but on overall it should be correct. Explanation: Get_Analog_Value(rc_ana_in01) >> 3 Previously it was '>> 2', because I'm doing a bit shift so that the range from 0-1023 becomes 0-254 (8bits) Now its >>3 as I'm sizing the range to 0-127 (7 bits) to be used in the calculation to scale set 1 (127 to 254) or set 2 (127 to 0). |
Re: Need help with PWM 1-2ms pulse control
Quote:
James' suggestions get into some interesting low-level programming tricks that you probably want to bypass for now. The same with the other math shortcuts suggested. Understand how you map from one range to another then you can play with shortcuts. (Nobody likes long division...) You already mapped one range into another when you took the analog 0-1023 and mapped it into the range 0-254. It's the same for going to the range 0-127 or 127-254 or any other range of data. It's just a ratio: analog input / analog full range = pwm output / pwm full range or input/1024 = pwm01 / 254 With a little math manipulation that ratio can be expressed as: pwm01 = (analog input) * 254 / 1024 where the 254 is your full pwm range (the range you want to end up at) and 1024 is the full analog input range (the range you start with). That's why replacing 1024 with 22 worked for you earlier. Your full range then was just 22. Instead of your answer: After pwm01 = (long) Get_Analog_Value(rc_ana_in01) * 254 / 2048; Keep the ranges you are working with (starting with a range of 1024 and ending up with a range of 127) and you'll get a more understandable result: After pwm01 = (long) Get_Analog_Value(rc_ana_in01) * 127 / 1024; ---------------- Here's the curve ball: All that works fine for ranges starting at zero, and it's not too hard to work the math around to a range of 127-254 by just adding 127. There is an additional robotics trick here though that throws a wrench into this second range, because 127, in the middle, is neutral. You should think about how you want your servo to behave when you switch between the two Sets. By just shifting the range up by adding 127 your servo will be at rest when the pot is all the way up, but at full speed when you throw the switch. You might want to think about having the pot be the same for both sets when it's in one position. That just means inverting the second Set range and making it 254-127 instead. Mapping an analog input of 0 to be 127 for both Sets will have your servo stopped for both Sets when the pot is all the way down, and at full speed in both when it's all the way up. Care to take a guess on how to invert the range 127-254 to make it 254-127 instead? You could instead invert 0-127 to make it 127-0 if that's easier to think about. Then add 127 to that. ------------------------------------- Switches: Using the default EDU code the first two ports (1 & 2) are analog inputs, the others are mixed digital INPUTS (6,8,10,12,14,16) or OUTPUTS (all the others). You can change these if you want where you saw the TWO_ANALOG setup before. Make sure you use an INPUT and just hook a switch between the signal and ground (DO NOT use the center +5v power pin). It'll appear in the code with a value of 0 or 1 and the code to check it looks like: Code:
pwm01 = (long) Get_Analog_Value(rc_ana_in01) * 127 / 1024; // It's going to end up in a range of 127 for either Set A or B |
Re: Need help with PWM 1-2ms pulse control
Haha, wow! You make it sound so simple. Heres my attempt....
I've been able to keep set B as Pwm=127 when pot is close to 0, and Pwm=255 when pot is close to 1023. As for set A, I did the plus 127 method. Pwm= ((analog signal) * -127 / 1023) + 127 so that gets me close to Pwm= 0 when the pot goes to 1023. close to Pwm=127 when pot goes to 0. This way, I've made the ratio a negative number, when I enter 1023 for the analog signal, the pwm will result in -127, so by adding 127 at the end, I will obtain 0 when the Pot is at 1023 or close to it. When the pot is close to 0, 0*(-127/1023) = -127 + 127, I get a 0 for the PWM. So this actually works out to this situation: Pot @ 1024 SetA Pwm= 0 SetB Pwm= 255 Pot @ 0 SetA Pwm=127 SetB Pwm=127 Il have to play with the numbers some more to give it a neutral band in the middle. This is all theory, but I've havnt tested it on my mini rc yet, so when I get back, ill' give it a try. |
Re: Need help with PWM 1-2ms pulse control
if (rc_dig_in06 == 1)
{ pwm01 = ((long) Get_Analog_Value(rc_ana_in01) * (127 / 1023) + 127); } if (rc_dig_in06 == 0) { pwm01 = ((long) Get_Analog_Value(rc_ana_in01) * (- 127 / 1023) + 127); } Tada! I think this is right, ill have to give it a try when I get home... |
Re: Need help with PWM 1-2ms pulse control
When you have two mutually exclusive tests like that, you can use the if statement's else clause.
Code:
if (rc_dig_in06 == 1)I'd actually have done it a little differently: Code:
pwm01 = (int)127 + Get_Analog_Value(rc_ana_in01) * rc_dig_in06?127:-127 / 1023; |
Re: Need help with PWM 1-2ms pulse control
If you're driving a victor from this, I don't think you need to worry about deadband. The victor has quite abit of deadband around the 127 region.
As for a servo.. well it may jitter around (not so sure). You may want to print out the values to screen to see how much its jittering at. Maybe add a small (0.1uf? 1nF?) capacitor from signal to ground for the analog input. That usually helps when my analog cable is non-shielded and very long... Edit: apologies for using bit shifting, so I shall add a bit to explain what it is >> is essentially known as 'bit shifting'. Skipping the complicated details, it is simply: a >> 1 same as a / 2 a >> 2 same as a / 4 a >> 3 same as a / 8 a >> 4 same as a / 16 The difference is that a bit shift operation takes significantly lesser processing time compared to a divide (unless compiler optimized). Similarly, a << 1 same as a * 2 a << 2 same as a * 4 and so on. |
Re: Need help with PWM 1-2ms pulse control
Thanks everyone! It works perfectly. Now im able to do exactly what I wanted =D. This might be a bit hard on the servo but I think it shouldnt be too bad. Im testing this on a small scale robot, just trying to come up with driving abilities...where at a flick of a switch, the robot can start driving backwards, essentially turning the rear end of the robot into the front. I think this helps the drivers a little since they dont move their joysticks in reverse.
|
Re: Need help with PWM 1-2ms pulse control
Is it possible to define a fuction?
#define let_go pwm01 = ((long) Get_Analog_Value(rc_ana_in01) * (- 127 / 1023) + 127) I need to set up an array of these functions, possibly even make it so that a bunch of pwms = to that function. |
Re: Need help with PWM 1-2ms pulse control
Oh wow!
Sorry guys, I've somewhat impatient, I've took the time to test this code with a #define. #define Let_go P1 = ((long) Get_Analog_Value(rc_ana_in01) * ( 127 / 1023) + 127) in this case, I defined Let_go to represent the P1 which is the pwm01. And everytime Let_go is called upon, the pwm output would correspond to the potentiometer that i am adjusting. Hahah this is so cool to see programming language turning into physical movement. Wonderful... |
Re: Need help with PWM 1-2ms pulse control
In the code, in the User_routine file, there is a fuction called Limit_Switch_Max && Limit_Switch_Min && Limit_Mix.
Do I need those? What is the purpose for that to be there? It appears to be some sort of drive system limiter. But is it okay it I delete that? Im using something else instead. Are the interrupts better digital inputs than making more digital inputs from the 1-16 pins? Im just courious as to if maybe the interrupts may have an advantage over the others since by default the are digital inputs. |
Re: Need help with PWM 1-2ms pulse control
Quote:
The Limit_Switch_Min/Max are examples of how functions work, while Limit_Mix is handy for making a joystick behave arcade-style. For what you're doing the interrupt digital inputs will behave just like the other digital inputs, so you can simply use them. The interrupt inputs have some special properties that make them useful in very time critical tasks. Measuring and reacting to things much faster than a hand operated switch. We take advantage of interrupts with special sensors or highly accurate timed events. ------------------ I'd take the parentheses away from your real code as Alan suggested in his previous post, or move them. In the integer math you're doing it's important to do all your multiplications first followed by any divisions. Code:
analog input * 127 / 1023 or (analog input * 127) / 1023So if analog input = 512 (halfway on the pot) analog input * (127 / 1023) would be calculated by the EDU as 512 * (0) because 127/1023=0.0254154 which gets truncated to the integer 0 If the parenthesis are removed (or moved) then (analog input * 127) / 1023 = (512 * 127) / 1023 = 8704 / 1023 = 85.33333 = 85 So the order you do calculations becomes very important. |
Re: Need help with PWM 1-2ms pulse control
Great! I totally forgot about that, I just put those brackets on just in case I get errors, I've seen at least 100 syntax error messages in about 2 real hours spent on programming. =D But I am contempt with my code as of now, it works the way I thought it would have.
Thanks for all the great support! Especially Mr. McLeod! Thank you so much! |
| All times are GMT -5. The time now is 08:54. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi