Am I doing ultrasonic PWM correct? It seems not

I am slightly discouraged, please don’t take my post to be too curt. I wrote a very long message detailing everything I understood about the code I was implementing. I then proceeded to ask if anyone can see what I’m doing wrong. I clicked submit, but something to do with the time it took me to write my post meant I had to log in again, and so I lost whatever I tried to post. Nothing in the cache. Eventually I’ll try to rewrite [and post elsewhere] my understanding of everything, because I think that sort of newbie-guide is missing to timer information. I read a lot about timers to try and understand what I was doing [4-5 hours this weekend], but I felt there could be a bit more information.

Anyway, I suggest either
(1) i implemented this code [i’ll post it soon] incorrectly.
(2) there’s something in the arduino environment that is overriding my setup.

Here’s my initialization code:

TCCR1A = 0xA2;  //Sets to 9-bit phase correct pwm. Note to self: Check the binary to figure out of it's the TOP set version or the regular version...I think it's regular. I don't set the TOP, it's assumed 9-bit.
OCR1A = 0;  //   0% duty cycle on OC1A (PB1)
OCR1B = 0;  // 0% duty cycle on OC1B (PB2)
TCCR1B = 1;

Explanation: TCCR1A is set to 162. This means I have 10100010. According to avrbeginners.net/architectur … html#tccra, I believe that means I’ve set COM1A1 = 1, and COM1A0 = 0. This means “Toggle OC1 on compare match.” So when timer1 = the value I put in for the duty cycle of pin 9 or 10, then they will toggle from HIGH to LOW and then [on the downcount] low to high. At the bottom two bits of 162, I can see “10”. This means PWM11=1, PWM10=0. This means Timer/Counter is 9-bit PWM. This means that it counts from 0 to 511. I hope I have also set it to phase-correct mode, so it counts from 0-511 and then 511-0.

Sidenote: I’m kind of curious why 10100010 was chosen. I got this number from, I believe actually ben’s code on these forums, but in reality it looks like only the first two and last two bits are used; the rest are empty…so couldn’t 10000010 work equally well?

Next I’ve set OCR1A and OCR1B to zero. This shouldn’t matter; just means a zero percent duty cycle for now.

TCCR1B is set to 1, which means NO prescale divisor. So timer1 ticks once per cycle, and at 20Mhz (baby orangutan here) means 20,000,000 times a second.

Here’s my function that changes the duty:

void HighFreqPWM(byte pin,int duty){  //Takes a duty of 0-511 for an input, does  19.6khz signal.
  if (pin==9){
    OCR1A = duty;
  }
  else{
    OCR1B = duty;
  }
}

So I change the value for the OCR1 that corresponds with the pin that I am trying to PWM (only either 9 or 10, the two pins connected to timer1.) The pin toggles when the timer reaches that value. So if you put something like 50, then for a brief period of time the pin is HIGH, until count=50 when it becomes LOW, and then it goes ~460 counts until 512, and then another ~460 counts from 512 to 50 again, and it becomes HIGH. Thus OCR1/511 = % duty cycle.

Since I am counting from 0-511, and then back down from 511-0, and ticking 20,000,000 increments a second, then I am making a cycle about 20mhz/1024 = ~19.5khz. This is exactly what I want to run my motor driver with an ultrasonic limit of 20Khz (the pololu one.)

However, my code doesn’t work! The driver doesn’t move, even though it works when I use the arduino enviroment analogwrite and don’t mess with the timer (i.e, I am running at ~610hz.) I DO have SLEW setup correctly for my >10khz signal.

[size=200]I am hoping I have written enough for someone else to offer insight. [/size]

I assume either
(1) I didn’t do what I wanted to do or think I’m doing.
(2) Don’t know that arduino environment is destroying what I’m trying to do
(3) Maybe - just thinking now- I am not implementing phase-correct PWM? If I’m not implementing phase-correctPWM [just fast-pwm] then I would be sending a 40Khz signal, which is faster than my driver can handle.

Hello,

I haven’t looked closely at what you are doing, but I wanted to throw in a quick observation about this:

The tutorial you posted a link to describes the AT90S2313 microcontroller, while the Baby Orangutan uses an ATmega328P. The registers in these two microcontrollers are not exactly the same; on the 328P, the highest four and lowest two bits of TCCR1A are used, as described on page 132 of the datasheet (found here). I suspect these differences (probably involving other registers as well) are ultimately the source of your trouble. If you don’t manage to work it out, hopefully I or someone else can take a closer look at your code tomorrow and suggest some changes.

- Kevin

This is why you’re a pro, and I’m just an amateur. Darn! I wish I noticed such a simple but fundamental mistake in my understanding.

Admittedly, that does explain my confusion in terms of understanding. However, I think I got my 0xA2 from code for the 328P.

So I have set COM1A1 =1, COM1A0 =0, COM1B1=1, COM1B0=0
This means both A & B are set to:
“Clear OC1A/OC1B on Compare Match when upcounting. Set OC1A/OC1B on Compare Match when
downcounting.” as long as i"m on phase-correct mode.
And WGM11 =1, WGM10=0
Which, according to this^, means I’m on 9-bit phase-correct mode, as long as
WGM12(CTC1) = 0, and WGM13=0.

WGM12 and WGM13 are set in the TRC1B register, which I set to 1, so only CS10=1, and the rest 0. In sum, I think it’s all correct.

[size=150]In summary:[/size]
You pointed out a fundamental flaw that I was reading from the wrong datasheet. But, I think my code which was scavenged in a large part from real people (real because they know what they’re doing, unlike me) was applicable…I merely did not understand correctly how it was working. Now, i think I have a better understanding.

I am not in a huge rush though, this is me trying to learn things outside my classes…I really appreciate all that Pololu has taught me ^_^. And, if it offers any encouragement to what must be overwhelming (offering such involved customer support), I’ll mention that I’m still consulting with the (very small) company I worked with last semester and offering support…They love to call you folks, which I think is much less efficient.

Hi, Tomek.

Before I spend too much time looking at this in detail, can you clarify if there is still a problem? If so, can you post your full code, the specific Arduino you’re using, and how everything is connected? Do you have access to an oscilloscope? If not, it might be simpler to put an LED on the output (with an appropriate current-limiting resistor) rather than your motor driver and check whether the brightness changes as you change the duty cycle. This would at least confirm that there is some kind of PWM appearing on that output.

- Ben

Ben,

That is a perfect idea- thanks! I do have leds and an extra Baby-O on hand, I’ll do the test this weekend. I ought to have thought of it.

Although I don’t have the motor driver on hand, I can certainly see if some PWM is working.

[size=150]
I’ll update this thread after I test pwm on an led. I won’t have time to get to it until friday evening.[/size]

That sounds good. When it comes to troubleshooting, whenever possible, simplify. With your current setup, the problem could be with interference from the Arduino environment, with your motor driver, or with your code. Taking the motor driver and Arduino out of the picture should make it a lot easier to determine if your code is good.

By the way, the our OrangutanPulseIn library might come in handy if you confirm there is some kind of PWM output and you want to determine the frequency (you could probably use the Arduino’s pulseIn() function for the same kind of thing). This example program might be helpful. To use it, you would want to change the pin on which you’re measuring pulses and connect that with a wire to the pin you expect to be outputting the PWM. You will also want to replace the LCD code with serial print statements if you have a USB-to-serial adapter.

If there is no sign of a PWM output, please let me know and I’ll look at your code in more detail.

- Ben

Thanks Ben,

I’ve definitively learned a lot here (and a few other places.) Simplifying seems key; I always welcome the helpful reminder.

[since you posted] I would like to update that I didn’t get time to update this weekend.

For now we delayed getting the ultrasonic PWM down, so that I could mess with making use of the current feedback (which I am using to limit the max torque [protect the gears] and as a rudimentary idea of how fast the motor is rotating, since the current tells me about the difference between applied voltage and backEmf. And backEmf tells me rotation speed.)

After midterms this week, I’ll be playing around with the code! Then, finally, will update.

The pulseIn information seems useful. I am surprised, though, that the code can be so quick as to count such a short impulse. I might also look into using the rudimentary scope functions of the pololu Avr programmer. Edit: nevermind! The avr programmer slo-scope has a 20Khz sampling rate, so I think since my signal would be 19.6Khz, I would not see anything.

It does it using interrupts, so it is really fast and minimally intrusive on the rest of your program.

- Ben

I’ve tested the ultrasonic PWM and am happy (though slightly annoyed) that it works perfectly fine on the LED. Gosh! It is great to have things physically in hand (i’m on spring break from school and can visit the project in person.)

Edit: In defense of the guy who I am working with, I have now tested the code in my setup, and have found it does not work in the complicated code. I am trying to trace the issue now.

Tomorrow I’ll use a scope (just as is it will be easier) to see what the frequency really is. If it is >20Khz, i will try to investigate what is not setup correctly. If it’s near 19.6, as I expect, then I will run it on the original code and not question why it was reported to me that it didn’t work.

Edit: I have tested with a scope, I got roughly 19.4k, so I think that’s perfect!! (It’s probably 19.6k but it’s hard to measure any better on this scope.)

FINAL VERDICT:

I could not find exactly what was messing up my subsequent calls to my highFrequencyPWM function. My sequence would go like this:

in setup, run “setupHighFrequencyPWM” or whatever that function that first establishes the prescalers is called.

In the main program I would run
(1)“Open a door, with a different motor, using traditional arduino analogwrite() on a different driver &pins”
(2)“Load belt with high frequency PWM” and it would do well (once I fixed some minor details on my end.)
(3)“Close door, using a function almost identical to Opendoor”
(4)“Go back to home with high frequency PWM”

By step 4, high frequency pwm would not work, presumably because something underlying in Arduino overrode some of the other settings. In fact, if I bypassed step four (manually completing it) and went back to step 2 (after step 1), then it would STILL not work.

I could not seem to isolate what in Arduino was causing this, however, my solution is to call my
"StartHighFrequencyPWM" setup code, every time I get into a function loop that frequently calls high frequency PWM.

[size=150]Thanks Ben! Your troubleshooting tips helped me work through the problem and isolate everything. The code seems to be right, and there’s something underlying in the arduino environment that I have to (and can easily) overcome with a simple tweak.[/size]

That’s weird and kind of annoying, but I’m glad you have a workaround! Thanks for letting us know about the problem and how you fixed it.

- Ben