Would you like to react to this message? Create an account in a few clicks or log in to continue.

You are not connected. Please login or register

SimulIDE_0.5.16-RC8_Win64 PWM/OCR bug in AVR?

2 posters

Go down  Message [Page 1 of 1]

TimFisch

TimFisch

I tried a AVR demo for a rising & falling tone output (files attached).
In older versions (e.g. 0.4.15-RC7) the sound output works fine, in 0.5.16-RC8 there seems no PWM output on the pin available.


Code:


// Deklarationen ==============================================================

// Festlegung der Quarzfrequenz
#ifndef F_CPU                   // optional definieren
#define F_CPU 12288000UL        // ATmega 328 mit 12,288 MHz Quarz
#endif

// Include von Header-Dateien
#include <avr/io.h>               // I/O Konfiguration (intern weitere Dateien)
#include <util/delay.h>           // Definition von Delays (Wartezeiten)

// Konstanten
#define MIN_PER     59          // minimale Periodendauer in "Timerticks"
#define MAX_PER     255         // maximale Periodendauer in "Timerticks"
#define WAIT_TIME   2000        // Wartezeit zwischen Flanken in ms

// Makros
#define SET_BIT(PORT, BIT)  ((PORT) |=  (1 << (BIT))) // Port-Bit Zustand setzen
#define CLR_BIT(PORT, BIT)  ((PORT) &= ~(1 << (BIT))) // Port-Bit Zustand loeschen
#define TGL_BIT(PORT, BIT)  ((PORT) ^=  (1 << (BIT))) // Port-Bit Zustand wechseln (toggle)

// Funktionsprototypen

// Hauptprogramm ==============================================================
int main()
{
 DDRB |= (1<<DDB0);            // Port B, Pin 0 (zur LED) auf Ausgang
 DDRD |= (1<<DDD5);            // Port D, Pin 5 (zum Buzzer) auf Ausgang
 TCCR0A = (1<<WGM01) |(1<<COM0B0);   // CTC Mode waehlen und Toggle Mode aktivieren
 TCCR0B = (1<<CS01 | 1<<CS00);       // Timer-Vorteiler /64
 
 OCR0A = MAX_PER;            // Start mit tiefstem Ton
 
 while(1)                    // Start der unendlichen Schleife
 {
 for (OCR0A=MAX_PER; OCR0A>MIN_PER; OCR0A--) // Frequenz erhöhen
 {
 _delay_ms(10);                          // in Schritten von 10ms
 }
 _delay_ms(WAIT_TIME);                       // Wartezeit hohe Frequenz
 TGL_BIT(PORTB,DDB0);
 
 for (OCR0A=MIN_PER; OCR0A<MAX_PER; OCR0A++)  // Frequenz absenken
 {
 _delay_ms(10);                          // in Schritten von 10 ms
 }
 _delay_ms(WAIT_TIME);                       // Wartezeit niedrige Frequenz
 TGL_BIT(PORTB,DDB0);
 }                           // Ende der unendlichen Schleife
}

// Funktionen =================================================================



Attachments
SimulIDE_0.5.16-RC8_Win64 PWM/OCR bug in AVR? Attachmentexample2.zip
You don't have permission to download attachments.
(2 Kb) Downloaded 1 times

https://wiki.mexle.hs-heilbronn.de/

arcachofo

arcachofo

Thanks, I will have a look as soon as possible.

arcachofo

arcachofo

I found the problem, but... is this what you expected? scratch

SimulIDE_0.5.16-RC8_Win64 PWM/OCR bug in AVR? Pwm_og10


------------------------------------------------------------------------------------------

EDIT:
I had a deeper look to your code and I think the simulation is doing OK.
In my opinion you should use OC0A pin, or if you want to use OC0B, then set OCR0B at the same value than OCR0A.

For example this code works ok for both OC0A and OC0B outputs:
Code:
// Deklarationen ==============================================================

// Festlegung der Quarzfrequenz
#ifndef F_CPU                   // optional definieren
#define F_CPU 12288000UL        // ATmega 328 mit 12,288 MHz Quarz
#endif

// Include von Header-Dateien
#include <avr/io.h>               // I/O Konfiguration (intern weitere Dateien)
#include <util/delay.h>           // Definition von Delays (Wartezeiten)

// Konstanten
#define MIN_PER     59          // minimale Periodendauer in "Timerticks"
#define MAX_PER     255         // maximale Periodendauer in "Timerticks"
#define WAIT_TIME   2000        // Wartezeit zwischen Flanken in ms

// Makros
#define SET_BIT(PORT, BIT)  ((PORT) |=  (1 << (BIT))) // Port-Bit Zustand setzen
#define CLR_BIT(PORT, BIT)  ((PORT) &= ~(1 << (BIT))) // Port-Bit Zustand loeschen
#define TGL_BIT(PORT, BIT)  ((PORT) ^=  (1 << (BIT))) // Port-Bit Zustand wechseln (toggle)

// Funktionsprototypen

// Hauptprogramm ==============================================================
int main()
{
    DDRB |= (1<<DDB0);            // Port B, Pin 0 (zur LED) auf Ausgang
    DDRD |= (1<<DDD5);            // Port D, Pin 5 (zum Buzzer) auf Ausgang
    TCCR0A = (1<<WGM01) | (1<<COM0B0) | (1<<COM0A0);   // CTC Mode waehlen und Toggle Mode aktivieren
    TCCR0B = (1<<CS01 | 1<<CS00);       // Timer-Vorteiler /64
    
    OCR0A = MAX_PER;            // Start mit tiefstem Ton
    
    while(1)                    // Start der unendlichen Schleife
    {
        for (uint8_t count=MAX_PER; count>MIN_PER; count--) // Frequenz erhöhen
        {
            OCR0B = OCR0A = count;
            _delay_ms(10);                          // in Schritten von 10ms
        }
        _delay_ms(WAIT_TIME);                       // Wartezeit hohe Frequenz
        TGL_BIT(PORTB,DDB0);
        
        for (uint8_t count=MIN_PER; count<MAX_PER; count++)  // Frequenz absenken
        {
            OCR0B = OCR0A = count;
            _delay_ms(10);                          // in Schritten von 10 ms
        }
        _delay_ms(WAIT_TIME);                       // Wartezeit niedrige Frequenz
        TGL_BIT(PORTB,DDB0);
    }                           // Ende der unendlichen Schleife
}

// Funktionen =================================================================


If I missunderstood your code, please let me know.


BTW: avr-gcc compiling and debugging in simulide is coming (already implemented in development version).


------------------------------------------------------------------------------------------

EDIT 2:
I was confused... comparator should trigger a match when TCNT0 = 0.
So your code should work.
Now it works if you set OCR0B to  any vale < OCR0A, but it doesn't work for OCR0B = 0.


------------------------------------------------------------------------------------------

EDIT 3:
Should be solved in Rev 607.



Last edited by arcachofo on Tue Sep 28, 2021 9:25 am; edited 3 times in total (Reason for editing : Add new information)

TimFisch

TimFisch

Hi, I used CTC mode for generating the PWM (see: https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf#page=79)

As far as I understand the datasheet, this should be independent from OCR0B, but only dependent on OCR0A, shouln't it?  scratch

avr-gcc compiling and debugging in simulide? yeah Cool !
I think not only the students will appreciate it.

is there an actual revision for Win10 somwhere available for testing?

https://wiki.mexle.hs-heilbronn.de/

arcachofo

arcachofo

As far as I understand the datasheet, this should be independent from OCR0B, but only dependent on OCR0A, shouln't it?
Well.. as I understand it, in CTC mode, OCR0A determines the TOP value for the timer, so the frequency.
But each compare unit triggers a match when TCNT0 = OCR0X:
Datasheet wrote:The 8-bit comparator continuously compares TCNT0 with the Output Compare Registers
(OCR0A and OCR0B). Whenever TCNT0 equals OCR0A or OCR0B, the comparator signals a
match.

So in this case Compare Unit A will trigger a match at the same time that Timer overflow: TCNT0 = OCR0A.
But Copare Unit B should trigger a match when TCNT0 = OCR0B.
The datsheet talks about using unit A in CTC mode, but not about unit B:
Datasheet wrote:For generating a waveform output in CTC mode, the OC0A output can be set to toggle its logical
level on each compare match by setting the Compare Output mode bits to toggle mode
(COM0A1:0 = 1).
But as I understand, just after overflow, when TCNT0 = OCR0B = 0, Unit B should trigger a match as well and toggle OC0B output if COM0B1:0 = 1.
So your code should work.


is there an actual revision for Win10 somwhere available for testing?
I just finished a massive refactoring related to the new Property system implemented (>300 files modified), so I'm doing some testing and fixing at least the most ovbious problems.

Anyway your code works if you set ORC0B = 1 (Indeed anything <59 should work in this case).
Or if you use OC0A instead of OC0B.

The problem in simulide was related to this:
Datasheet wrote:A match will set the Output Compare Flag (OCF0A or OCF0B) at the next timer clock cycle.
Simulide was doing it in the same clock cycle, and if OCR0B = 0 then the number of simulation cycles were multiplied by 0, so actually cancelling it.

Sponsored content



Back to top  Message [Page 1 of 1]

Permissions in this forum:
You cannot reply to topics in this forum