Automatic counter-Encoder

Hi everyone, I dont know much about programming so please help me out. Thanks!

Im looking for a way to make a counter that counts from 1-30 or 0-29. A total of 30 units. I have a clicker hooked up to a wheel and everytime the wheel moves 12 degrees i get a steady 1 or a steady 0 at the digital input. A total of 15x 0’s and 15x1’s willl be observed. I need a code that adds 1 everytime the input changes.

Starting with 0 , 1 , 0, 1, 0 , 1 , 0, 1, 0 , 1 …etc
The counter: 1 +1 + 1+1+1+1 +1 +1 +1 +1 each time…and then everytime a 1 has been added, it keeps that value, untill the next 1 gets added.

Example: I can retrieve a number from the counter and if the number is 23, i make the PWM = 127, when the number is 24, i make the pwm = 135…etc

When the number reaches 29 or 30 depending if you started with 0 or 1, the next digit 30 or 31 does not exist and automatically resets to 0 and starts all over again…

Please point me in the right direction. My knowledge of C is limited to what I’ve been able to understand from examples and IFI mini RC programming guides.

Yes, I am using the Mini RC, EDU controller.

id reccomend setting up an interrupt and attatching your encoder clicker to the interrupt ports on the edu-RC.

from there, you can add the signal to a stored variable, which will cause the integration you are looking for.

as for resetting after 30… you can do something like:

if (clicks % 30 == 0) {
clicks = 1;
}else{
clicks += input;
}

I have a feeling that you may have to connect the same clicker output to two interrupt pins, and have one trigger on the rising edge and one trigger on the falling edge in order to do what you want…don’t the PIC interrupt pins only trigger on either rising or falling, and not both? I guess I’m not quite sure about this…it depends on how the microcontroller is configured in the RC…

For starters look at Kevin Watson’s excellent repository of FRC code and FAQ’s.
http://www.kevin.org/frc/

Specifically for the EDU Controller read the encoder_readme.txt within the zip on how to make the code work with the EDU controller.
http://www.kevin.org/frc/frc_encoder.zip

Now if I remember correctly digital ports 3 through 6 are designed to interrupt on both the rising and falling edge. So if you connect your clicker to one of those it will trigger an interrupt on 0,1,0,1,0 and so on. Simply remove the “Phase B” logic and it should work as you need.

Ah, I see. I just looked up the internal wiring diagram for the RC, and yeah, digital inputs/outputs 3-6 on the RC appear to be connected to port B on the PIC, which has that functionality.

Thanks, Phalanx.

Oh jeeez. Look, how fast is this “clicker” going to be clicking? If it’s slower than 38 times per second you could have the code to do this in your slow loop. If it’s slower than about 300 times per second (your wheel is turning slower than 600 RPM) then you can almost certainly put the checking code in your fast loop and just not worry about the complication of interrupts. The code itself is simple.

count = (count + ((dig_in ^ old_dig_in)?1:0))%30;
old_dig_in = dig_in;

And you’re done. ^ is the bitwise XOR operator, it’s true if both arguments aren’t the same. So if the current input isn’t equal to the old input, you add 1. Otherwise you add 0. And then you modulo by 30.

Unless you absolutely have to not miss any of the clicks and it’s turning at some ludicrous speed, just plop that in your code with dig_in replaced by the actual digital input and don’t worry about interrupts.

THATS the operation i was looking for in my suggestion… i guess thats why i shouldnt be programming before noon.

One thing to keep in mind when using interrupts, is that if you use a mechanical switch to trigger it, the mechanical switch doesn’t cleanly fire just once. It tends to trigger the interrupt anywhere from 10 to 100 times. I learned this a couple of years ago with a mechanical mouse encoder hooked up to our robot. Optical switches don’t have this problem.

I only bring this up because you don’t say what type of switch you are using.

If you want to avoid using interrupts, you could place Kevin Sevcik’s code sample in Process_Data_From_Local_IO() within user_routines_fast(). It may give you more accurate readings if you really need that.

I’ve never had any issue with any mechanical switch generating spurious interrupts, but that has only been my experience. I find with higher quality components that becomes less an issue.

Mechanical switches are pretty notorious for bouncing, but typically under light switching force, so the contacts only slowly make contact and the resistance of the connection fluctuates a bit. You can account for this with some debounce logic in the fast loop as well, by checking to make sure the last two or three samples of the input are the same.

Part I:

Woah there! Plenty of help, thanks!

As for Kevins code: count = (count + ((dig_in ^ old_dig_in)?1:0))%30;
old_dig_in = dig_in;

Do I simply replace dig_in with rc_dig_in05 for example if im using digital 05 as my input. Will I have to replace old_dig_in with anything or leave it as is…

So everytime I need to call back to find where the count is, I have to refer to using “count”? right? so in the case that count = 25 is true, do this etc etc…if count is 26 do this and so on. Would it be possible to start the count when the switch is either a 0 or a 1? For example, I always want the first number 1 to be when the switch is 1, and then when the switch is 0, that would become 2, if I had to reset, and the current switch is sitting at 0, it would not start the count unless the switch is at 1.

So can someone run this through with me? When the system boots up, what is it doing initially? It has no count to begin with? Does it start counting as soon as it detects that a change has occured?

Could it be made so that initially, if the switch is 0, it would count it as a 1, and when the switch starts with a 1, it would count is as an automatic 2. This way, each 0 that comes back from the switch becomes an odd number, while each 1, is an even number.

If you are wondering what this wheel is, it is actually a motor that I’ve been making in the shop. its made to track distance covered by the rotations.

Part II:

How do I print the current count in a printf format?

alright, so first, this is a 0-29 counter.

Second, yes you can leave old_dig_in as is. I’d recommend renaming it old_rc_dig_in05, though, in case you want to duplicate this code for another counter.

Third, as I said, ^ will be true and you’ll increment your count whenever rc_dig_in05 and old_rc_dig_in05 aren’t equal. So logically, it doesn’t count when those two are equal. So, if you want count to start at 0 if rc_dig_in05 = 0 at the start, then what would you want to set old_rc_dig_in05 equal to to start out? If you get that right, then your second desire follows naturally.

You’ll need to set count = 0 in your definition or in the initialization code or some such to have it start as 0. Or set it to whatever you like, but do recall that this is a 0-29 counter.

The printf would be printf(“blah-ty-blah %d”, (int) count); And the (int) IS important, as printf expects ints, and you can get some odd results giving it a char. (And you should be using a char for this.)

Finally, this only counts in one direction, if you want to change directions, it’ll be a little different.

There is a 0.625 - 0.635 Khz frequency producing only 0.9volts at the digital outputs. I’ve tried other digital outputs and they do the same thing. And the solenoids also give me that sort of frequency response. I measured it with a multimeter, FREQ% selection. What could cause this?

I will give the code a try, so far, im still trying to solve some other minor issues such as the one above.

your digital I/Os are pulsing? check your interrupts to make sure nothing funky is emulating a pulse-width-modulator there…

Yes, I checked, in fact theres nothing connected to them. In the user ini, it was left untouched, except a few modifications to analog inputs, digital outputs and dig inputs. Thats now, a series of relays connected to the digital outs, 4 servos at pwm outs, no pwm inputs, 5 analog inputs, 2 solenoids.

So it was all in the programming. I dont know how it happened, but I think there is a conflict with my codes. At the very bottom of the code, I have an else statment, and under tthat all the pwms would become 127, all the relays, solenoids would become off. But when I changed that to all being on.

and loaded the program into the RC. I got tthis super fast clicking response. all my relays were firing like a buzzer and so were the solenoids!!! freeky!!

I think the problem is from all my if’s …

if …
{
blah blah blah
}
if…
{
robot is hungry: Go to macD’s
}
if…
{
The rise of machines, assimilation !=1
}
else
{
shut down everything
}

Thats pretty much what my code looks like…
if…

You need to walk through your code step-by-step and make a logic table of what the code will do at each step. It sounds as if your logic is doing one of your “if”'s when it goes through your statements, then the very next time through it’s deciding to do something different.
You’ll get a pulsing as fast as your code changes it’s mind. On the EDU this loop of your’s can change it’s mind 59 times a second in user_routines.c.

“If” the contents of each of your if statements is supposed to be mutually exclusive, then you should probably be using “else if” statements instead. That just keeps them from trying to do three different actions at the same time. The last if will win.

For example:


if ....
{
    blah blah blah
}
else if.....
{
    robot is hungry: Go to macD's
}
else
{
    shut down everything
}

would it still be correct if I did it in this way:

if…

else if…

else if…

else if…

else…

Are there any limits on how many else if’s I can use?

That’s correct.

There isn’t a limit on how many you string together.
After a couple of pages it will become unreadable though…

Read Mark’s answer as:
After a couple of pages, you might want to figure out how to do this with a switch-case structure or something else.

Switch-case structures are especially nice for implementing a state machine to simplify things like this. Assuming you’re using this to make certain moves at certain distances traveled, you can make all the moves relative to the last one. So if you discover you need to travel 5 more inches halfway through your 20 step sequence, you only have to change 1 number, not 10.