Go Down

Topic: Problem!! PWM frequency UNO vs MINI (Read 731 times) previous topic - next topic

HanFre

Hi

I'm having some trouble with the PWM frequency on a MINI.
We are going to use this to make a 0-5V signal to a NI-daq logging unit. (RC-filter)

I'm transfering the code below to an UNO(SMD) and the frequency is around 15kHz...
The same code transfered to the MINI and the frequency is around 15Hz???  :o
It's the the same smd chip, Atmega328P, on both boards...

What are the difference between the two boards?
The scope is measuring 16MHz on the crystal on both...
Is there a difference in fuse bits?

Sorry, in advance if my writing is not 100%
Best regards from Norway

Code: [Select]

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

volatile unsigned long totTime;
volatile unsigned int startTime, endTime;
volatile unsigned int teller=0;
volatile unsigned int overFlow,  nyFlow, lastcount;

volatile boolean startEnd = false;



int main(void)
{
 
  Serial.begin(115200);
  cli();
 
  DDRB |= (1 << PB1); //Set Pin9/13/PB1/ICP1 as output for PWM
  DDRB &= ~(1 << PB0); //Set Pin8/12/PB0/OC1A as input for timestamp for frequency

  PCICR |= (1<<PCIE1); //Pin change interrupt PCINT[14:8]
 
  TCCR1A |= (1 << COM1A1) | (1 << WGM11) | (1 << WGM10);                //COM1xn set how the waveform will be on the output pin.
                                                                        //WGM1n in TCCR1A and TCCR1B chose what waveform generation mode to choose. Here it's set to mode 14: Fast PWM, ICR1 is top value.
  TCCR1B |= (1 << ICES1) | (1 << CS10) | (1 << WGM12);                  //ICES1 Witch edge the ICP1 is used to trigger a capture event. If set to 1, capture happens on positive edge.
                                                                        //
  TIMSK1 |= (1 << ICIE1) | (1 << OCIE1A) | (1 << TOIE1);                //ICIE1 enables input capture interrupt. OCIE1A enables output compare match A interrupt. TOIE1 enables Timer1 Overflow interrupt.
 
 
  sei();
  OCR1A = 512;

  while (1==1)
  {
  }
}

pert

I'm curious about the comment on this line:
Code: [Select]
DDRB |= (1 << PB1); //Set Pin9/13/PB1/ICP1 as output for PWM
Which pin on the board are you measuring?

Is there a difference in fuse bits?
The only difference is related to the different bootloader sizes:
https://github.com/arduino/ArduinoCore-avr/blob/58006613a7c858417881744419c5da54cc21a401/boards.txt#L67-L69
Code: [Select]
uno.bootloader.low_fuses=0xFF
uno.bootloader.high_fuses=0xDE
uno.bootloader.extended_fuses=0xFD

vs
https://github.com/arduino/ArduinoCore-avr/blob/58006613a7c858417881744419c5da54cc21a401/boards.txt#L444-L462
Code: [Select]
mini.bootloader.low_fuses=0xff
...
mini.menu.cpu.atmega328.bootloader.high_fuses=0xd8
mini.menu.cpu.atmega328.bootloader.extended_fuses=0xFD

of course that assumes the fuses on both boards are actually set to the Arduino defaults.

HanFre

thanx pert!

I'm going to measure the timestamp on Input Capture Pin, Pin 9 on the MINI(rising)...

But that is not important right now, what I'm wondering is why do I get different frequency on my pwm when I'm using the same code, on an UNO(328P) vs an MINI(328P)?

And what can I do to get the MINI to give me higher frequency?

and btw what does the low_fuses=0xff vs low_fuses=0xFF (same right?)
and High_fuses=0xDEvs High_fuses=0xD8?

I got a avr Dragon so I can see the fuse bits on the UNO, but I can't get contact with my MINI... anyone got a drawing?

thanx!!
HanFre

CrossRoads

High fuse DE, 11011110 vs D8, 11011000, would only affect the Boot size. (512 bytes or 4096 bytes)

How are the low fuse bytes set? That has the divide by 8 bit and the clock source bits.
Does the mini have an 8 MHz resonator or a 16 MHz resonator?

The Programmer needs to connect to Reset, Power, Gnd, SCK (D13), MISO (12) and MOSI (D11).
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

pert

and btw what does the low_fuses=0xff vs low_fuses=0xFF (same right?)
Yeah, it's just sloppy inconsistent formatting in their boards.txt but it makes no functional difference.

cattledog

Quote
'm transfering the code below to an UNO(SMD) and the frequency is around 15kHz...
The same code transfered to the MINI and the frequency is around 15Hz???  :o
Are you sure of this? Are you using the Arduino IDE?

When you use |= to set up TCCR1A and TCCR1B you are not clearing the presets used by the IDE to set up Timer1.

On the Uno, you will be in mode 7  (bits set in WGM12:WGM11:WGM10) which is fast PWM to 1023, but the prescaler will be 64 because both CS11 and CS10 are set by the IDE, and you are not clearing CS11. Frequency should be about 235Hz.

Initialize the registers with TCCR1A =0 and TCCR1B = 0 before you set them up. If you do that, you should be set up for 15Khz.

I don't think there are different Timer1 presets on the mini and the uno, so I can't address the difference you are seeing.

HanFre

Thank you cattledog!!!
That seemed to fix my problem!!!
I now get 15kHz PWM frequency on both boards! at OCR1A = 512; I get an avarage voltage of 2.5V  :D
I'm so happy now!

resetting TCCR1A/B ( =0 ) first, then setting the right bits...
So the setting/resetting of those registers is just initially random then :o

So there shouldn't be any difference on the initial setting between UNO and MINI, I just have to have control on the bit setting, by resetting the whole register first!!

Thank you so much for your help!

regards
HanFre

cattledog

#7
Nov 24, 2017, 05:34 pm Last Edit: Nov 24, 2017, 05:35 pm by cattledog
Quote
So the setting/resetting of those registers is just initially random then :o
No. The timer registers are set to documented initial states.. Timer 0 is set up to control millis() and Timer 1 and 2 are set up to produce phase correct hardware PWM with analogWrite(). The Timers are set with prescalers of 64.

The timer set up is done in a function called init() in a file called wiring.c. This is part of the  IDE, and you can find it on your computer at

C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino\wiring.c

For debug purposes, you can always show the value of any timer(or any other) registers with serial prints like this. It's good to check what you actually get when setting up registers with custom values.
 
Code: [Select]
byte timerRegisterValue = TCCR1A;
Serial.print("Timer Register TCCR1A = ");
Serial.println(timerRegisterValue, BIN);
;


Go Up