100kHZ PWm on arduino UNO?

holy smokes that was a quick response. Thank you. Where are you getting this info, looking at the picture? Buzz it out, you mean like a continuity test with my DMM? My probes are a bit thick to be prodding around this little 328 chip.

Thanks again, John

EDIT** ah yes I see. Looking at the picture and the data sheet I can see that OCR2B is connected to d#3. What I don't see is why mine doesn't seem to be working. My osocpe is a sound card type so I can't test this with it.

Is there something wrong with the code I've shown above? Am I supposed to be setting a value for both OCR2B and TCNT2 for pin 3? I see section 18.5 of the atmega328 datasheet is talking about the two values matching or not, but sadly I don't understand all of this well enough [u]yet[/u] to really make sense of what I'm reading.

Thank You, John

Is there something wrong with the code I’ve shown above? Am I supposed to be setting a value for both OCR2B and TCNT2 for pin 3?

Your fragment of code looks OK. Are you having problems?

TCNT2 is constant cycling from 0 to a top value of 159 which you have set with OCR2A. 160 counts. The timer counts up (TCNT2 represents the value of the count) and resets itself automatically.

You have set outputB to go high at a count of 0 and turn off when TCNT2 matches OCR2B.

There may be some confusion caused by the fact that in your code the register values,TCCR2A and B, are set with HEX values, and you need to work that back to which bits are set in order to match up with what you read in the data sheet.

Hey CattleDog,
Yes I’m having problems. I get nothing from pin 3 like this. If I just go back to analogWrite(3, val); it works fine except for it’s doing so at like 750hZ.

That’s not “my code”. I copied and pasted that from the first page of this thread. I have only been trying to wrap my head around this HEX stuff for a couple of days now without much effort and as a result, without much success. I don’t know hex or binary and want to learn both but right now does not seem like a good time ( for whatever reason…).

I also don’t know what the TCCR and OCR stuff is. I know it sounds super lame, but this is all pretty new to me. I’ve got years of programming under my belt, but not for micros.

In short; please help. My little Pro Trinket is running at 12hz. I need a PWM speed of 100kHz and a variable duty cycle. I have the variable part already worked out based on user settings either current settings or those stored in eeprom.

I am currently soldered onto pin 3 for pwming.

Please and Thank You, John

So far my understanding of hexadecimal is like an odometer that counts from 0-9 and a-f before rolling over. So, 0x23 is 35 and 0x09 is just 9. So I’ve set OCR2B = 0x2d; to get a duty cycle of 45 and it doesn’t make pin 3 read give any signal. I’ve also tried calling pinMode(0x03, output) which also did not work.

You really need a scope to figure out what is going on, but I have tested the 100khz Timer2 code with software on a UNO as best I could. A basic frequency counter shows 100Khz when OCR2B is set to 10. Jumper pin 3 to pin 2.

volatile unsigned long count;

void countISR()
{
  count++;
}
void setup() {

  Serial.begin(115200);
  Serial.println("starting interrupt count");
  attachInterrupt(0, countISR, RISING); //INT0 pin2 (Atmega328)

 pinMode(3, OUTPUT);
  TCCR2A = 0x23 ;
  TCCR2B = 0x09 ; // mode 7, clock prescale by 1
  OCR2A = 160-1 ;  // 160 clock periods = 10us per cycle
  //OCR2B =10 ;
  TCNT2 =0 ;
}


unsigned long lastSecond;
void loop()
{
  OCR2B = 10;
  if (micros() - lastSecond >= 1000000L)
  {
    lastSecond += 1000000;
    noInterrupts();
    unsigned long copyCount = count;
    count = 0;
    interrupts();
    Serial.println(copyCount);
  }
}

I have also used a pulse width program from Rob Tillart and can read 2 us for OCR2B = 31(20%) and 5 us for OCR2B = 79 (50%)but things are not solid at the shortest periods. Jumper pin 4 to pin 3

//
//    FILE: PulseWidthMeter.pde
//  AUTHOR: Rob Tillaart
//    DATE: 2012-apr-01
//
//    LINK: http://arduino.cc/forum/index.php?action=post;topic=96971.0
//

#include <avr/io.h>
#include <avr/interrupt.h>

volatile unsigned int count = 0;
unsigned int pulseCounter = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println("PulseWidthMeter (timer1) 0.2");
  pinMode(4, INPUT); //jumper pin 4 to pin 3

  pinMode(3, OUTPUT);
  TCCR2A = 0x23 ;
  TCCR2B = 0x09 ; // mode 7, clock prescale by 1
  OCR2A = 160 - 1 ; // 160 clock periods = 10us per cycle
  //OCR2B = 31 ;//20% duty cycle 2 us long
  OCR2B = 79;//50% duty cycle will be 5 us pulse
  TCNT2 = 0 ;
}

void loop()
{
  // reset Timer1 registers and the counters (timer must be stopped before reset of counters!.
  TCCR1A = 0;
  TCCR1B = 0;
  count = 0;
  TCNT1 = 0;
  TIMSK1 = (1 << TOIE1);                      // enable Timer1 overflow interrupt:

  while ((PIND & B00010000) == B00000000);    // wait for HIGH
  TCCR1B |= (1 << CS10);                      // Set CS10 bit so timer runs at clock speed: 16 MHz
  while ((PIND & B00010000) == B00010000);    // wait for low
  TCCR1B = 0;                                 // stop counting
  pulseCounter ++;

  // Read the counters and convert to long
  unsigned long total = count * 65536L + TCNT1;  // Might need a +1 to correct start/stop calibration.
  float usec = (1.0 * total) / 16;

  // Display values
  Serial.print(total, DEC);
  Serial.print(" \t ");
  Serial.println(usec, 1);
  Serial.print("pulses: ");
  Serial.println(pulseCounter);
}

// count the overflows in IRQ
ISR(TIMER1_OVF_vect)
{
  count++;
}

Edit: If all you have is the trinket, you will have problems troubleshooting as there is no INT0 on pin2. There appears to only be one external interrupt on pin 3 which you are using for output. For the first sketch I think you can use attachInterrupt(1, countISR, RISING); and the pin will work as both input for the interrupt and output for the pwm. I’ll take a look at the second sketch and see what it takes to move the input to something other than pin 2.

Second edit:
I have modified the second sketch with pulse length counter to now use digital pin 4 for input.

Unfortunately I do not have pin 2 or 7 available as they are not "broken out". On the trinket they are used for USB bootloader. I also have no serial. I use oled for everything like this. I do have my oscope hooked up though and have set OCR2B = 1 and OCR2B = 2. I can see Frequency spikes now, but even with these low settings I get frequency readings all over the place. Anywhere from 300hZ to 1.4kHz. I get huge negative voltage spikes and hardly break the positive voltage range on other spikes. I either get a 0 or a negative reading on my DMM. Connecting an LED does nothing at all though I guess it wouldn't with a negative 4.2v.

I'm still waiting for some kind of a response over at the adafruit forum. In my defense; I had never even heard of Arduino before starting this project. This is my first ever and I started with one of the products. The stuff seems to be good quality and it's made in the U.S., it's a bit costly compared to other arduino knock-offs, but the support just isn't there.

Of course I have my code all saved in files. At this point I feel like putting all this adafruit stuff into a durable plastic bag and going at it with a big fricken hammer. At least then I'll know why it's not working.

Sorry to put you all through this. I really do appreciate your playing along though.

John

EDIT** so worked up I cant type properly at the moment. Several edits not noted...

have set OCR2B = 1 and OCR2B = 2

Make life a little easier on yourself and keep OCR2B set higher until you know what is going on. Use OCR2B = 80 for a 50% duty cycle. It will be a 5 us pulse length and the pwm period will be 10us = 100khz.

You can put OCR2B as high as 158 and then you will get almost 10 us pulse width.

The 12Mhz trinket processor speed will slow everything down from the 16Mhz values.

I also have no serial.

Can you get serial hooked up. Trouble shooting without it will be much tougher.

I'm working on making an FTDI to USB cable now. Not sure that I can yet, Not sure what it is really but trying to get it all worked out. There's an FTDI breakout on this pro trinket, I just don't know where all the pins should go on a usb cable yet.

EDIT** Hey cattle, you are around PA or OH are ya? I'll drive hours right now to get this onto a real scope. Apparently I'm not going to be making an FTDI cable without some extra parts. Not just an old USB cable...

Can you think of any Comp hardware that would have the chip I would need? I've a ton of extra computers, and components here.

Just order one. $6.90, I use these a lot. http://www.tinyosshop.com/index.php?route=product/product&product_id=186&filter_name=ft

I probably will. I guess it's actually called an FTDI chip. Surely there isn't one in any device I have laying around here. Trouble is I want / need it now. Thanks for the link

Surely there isn't one in any device I have laying around here.

Probably not.

I'll be purchasing an UNO tomorrow provided our local radio shack still has one. Maybe they have also have an FTDI cable on the pegboard.

Thank you guys and goodnight. I've a few Yuengling Black & Tans in fridge!

OK, no good O'scope, and no Serial print. Tough conditions for a timer code project. :(

Here's another possibility for trouble shooting whether or not you have pwm action on pin 3 with the timer manipulations as well as with analogWrite(3,value).

From my review of the anlogWrite() function in wiring_analog.c which is in C:\Program Files (x86)\Arduino\arduino-1.6.4\hardware\arduino\avr\cores\arduino I'm certain that if the function is working, than the code you have should be working as well.

One difference is in the prescaler for the timer, so if you try slow the timer setup back to where the default value is, you should perceive the code to be working, by whatever means you say that analogWrite(3,value) works.

The prescaler is set by the lowest three bits in TCCR2B and they are selected of by the line in the code

TCCR2B = 0x09 ; // mode 7, clock prescale by 1

Part of this value 0x09 is the value in bit 3 (WGM22) which is part of the fast pwm mode 7 selection. It's an unfortunate complication that the Timer Mode selection bits are spread across two registers.

You can change the prescaler selection as follows

TCCR2B = 0x09 ; // mode 7, clock prescale by 1 
TCCR2B = 0x0A ; // mode 7, clock prescale by 8
TCCR2B = 0x0B ; // mode 7, clock prescale by 32
TCCR2B = 0x0C ; // mode 7, clock prescale by 64
TCCR2B = 0x0D ; // mode 7, clock prescale by 128

The default prescaler for Timer 2 is 64, so as you increase the prescaler I believe you should see your code begin to "work".

If there are still problems, then you can try going to mode 5 (phase correct pwm to OCR2A), but the duty cycle selection sensitivity will be cut in half as top value of OCR2A will be 80. Default mode for Timer 2 pwm is phase correct pwm to 255 with a prescaler of 64.

I understand that you are driving a MOSFET with the pulses. Do you have the specs for it, and is it indeed rated for 100khz? Where does the 28% duty cycle come from?

Hey Cattle, Even after a few beers I still couldn't sleep thinking about this. Well I can but I keep waking up. Hate it! Anyways, that's kind of what I was thinking but still had no idea how to accomplish slowing down what I've just fumbled through speeding up.

I don't think I'll go at it right now, but thank you very much for posting back again. The mosfet I'm using is https://www.digikey.com/product-detail/en/STP27N3LH5/497-9095-5-ND/2136055 and I'm really not sure if it can respond as quickly as I'm now asking it to. I cant find anything regarding response time in it's datasheet. I do have a couple of better mosfets and inductors on the way though.

I was also thinking about using a small cap as a kind of filter or catcher so I can use my dmm to measure voltage. The meter didn't have any trouble keeping up at 750hZ but then again I'm now shooting for 10 times that speed...

Lots and lots of learning to do before this is going to work like I want it to. Again - I thank you all, John

ok, my mosfets were apparently tested at the factory at 1mHz so that's not the issue. I have my DMM connected to GND on the board and to pin 3. I have tried every one of the settings

setup{ //TCCR2B = 0x09 ; // mode 7, clock prescale by 1
 //TCCR2B = 0x0A ; // mode 7, clock prescale by 8
 //TCCR2B = 0x0B ; // mode 7, clock prescale by 32
 TCCR2B = 0x0C ; // mode 7, clock prescale by 64
 //TCCR2B = 0x0D ; // mode 7, clock prescale by 128
}

with

loop{
//OCR2B = 10;
OCR2B = 60;
//OCR2B = 100;
}

each of these and more. Nothing at all. I do get about 2.7v during reset though, but nothing when I press my fire it up button which is what should trigger the PWM.

Now If I get rid of all of this timer changing code and go back to just analogWrite(3,val) where val is anything from 1 to 255 I get voltage on the meter. My oscope also gives me a very acruate frequency reading of right at 750 +/- a couple of tenths.

Ok, a strange thing is happening. Using all of what I just posted in the setup and loop - if I begin holding the pwm button down during the reset cycle as it's turning back on then I do get a voltage on the DMM and the voltage will stay just as long as I keep pressing the button. Once I release it though pressing it again does nothing for voltage on the DMM but I still get my indicators on the OLED letting me know that my code is being triggered. The exact same code that works just fine with analogWrite.

I am so confused.

EDIT*** Just thought I leave all previous posted info here in case someone else is having the same problem ever, or just following along for a laugh.

in my loop I said if(button press){ OCR2B =100; }else{ analogWrite(3,0); }

I had never made it past trying to get the speed to change. Never made it back to my else statement and apparently the analogWrite in the else was ruining the whole thing. Typing out my last post about it working as long as I was holding the button during reset mode tipped me off.

I've still some more testing to do now. I'll likely post back soon. Thanks again.

apparently the analogWrite in the else was ruining the whole thing.

If you look in the source code for analogWrite, you find that analogWrite(pin,0) implements a digital write LOW.

pinMode(pin, OUTPUT);
 if (val == 0)
 {
 digitalWrite(pin, LOW);
 }

It appears that any subsequent hardware timer output pin HIGH/LOW does not override the software setting to LOW.

I'm trying here guys, something is not computing... Is it possible to get above 100kHZ?

Here's what I'm using. Given I don't fully understand it, I have been plugging away but every attempt only seems to slow me down.

TCCR2A =0x23; TCCR2B = 0x0A ; OCR2A =160-1; OCR2B =0; TCNT2 =0;

Also, if 100kHZ is the limit. Would it be possible to increase the PWM then by also increasing the clock speed? Not sure that I'm asking this correctly. I guess I mean overclocking the arduino itself...

Thank you, John

bumba000: I'm trying here guys, something is not computing... Is it possible to get above 100kHZ?

Yes, of course it is. The processor runs at 16 MHz so you could get 8 MHz PWM.

bumba000: Also, if 100kHZ is the limit. Would it be possible to increase the PWM then by also increasing the clock speed? Not sure that I'm asking this correctly. I guess I mean overclocking the arduino itself...

It isn't the limit, you are just guessing here.