I'm trying to generate PWM wave but it seems that proteus has a problem with it. I've tried to do so using CMSIS and CubeMX and neither of them works.
tested timers: TIM 1, 2, 4, 5 with all their channels
Timer configuration in CubeMX
Proteus Result
Edited:
CubeMX doesn't generate HAL_TIM_PWM_Start as part of the generated codes for TIM's. adding HAL_TIM_PWM_Start to the code and changing the value of Pulse to a non-zero amount, fixed my problem.
You should set Pulse value greater than zero. It is the PWM's duty value.
Related
I am using STM32 cubeMX for configuration and Keil for programming.
Have set onboard led pin pc13 pin as an output pin and default in push-pull mode. Set debugger to the serial wire as I am using ST-link V2 as a debugger. RCC set HSE to crystal/ceramic resonator.
and clock configuration set to default and generated project.
Now I started with a simple LED blink program. As below
HAL_GPIO_TogglePin(led_GPIO_Port,led_Pin);
HAL_Delay(1000);
build successfully with no error and uploaded and wonder my led was not blinking and shocked as I have done this before and now this is not working.
when I debugged step by step and my code was just going from two functions repeatedly.
while ((HAL_GetTick() - tickstart) < wait)
{
}
__weak uint32_t HAL_GetTick(void)
{
return uwTick;
}
Nothing happens more in this code I know the code is right but there is some error in the HAL_delay configuration.
After scratching my head for a day I tried uploading the following code
HAL_GPIO_TogglePin(led_GPIO_Port,led_Pin);
HAL_Delay(100);
And strange thing is that now my led is blinking only I have change the HAL_dealy value from 1000 to 100 and it works fine but, when using 1000 does not work at all.
So for testing, I gradually increased the delay value and I find that more than HAL_delay(400) it does not work.
Not able to find cause for this Any help will be appreciable.
As suggested by Tom I debugged uwTickFreq using STstudio.
and I got the following output waveform.
After that, I also uploaded the following code. And defined a variable as "unsigned long int a;"
HAL_GPIO_TogglePin(led_GPIO_Port,led_Pin);
HAL_Delay(100);
a= HAL_GetTick();
Now I debugged the value of a using STstudio. And strange the value of a becomes 0 once it reached around 300.
It seems like finally, I got the problem when I noticed the reset problem in the controller I searched around and find something here.
So I checked my optional bytes set in MCU with the STM32 cube programmer.
It was set as below.
Therefore I enabled these three optional bytes.
And the problem of reset was gone and I am now able to use the HAL_delay function properly and now the value of HAL_GetTick() is also increasing more than 300.
Still have one dought I think watchdog was causing reset but why it only cause that when I use the timing function.
I'm new to ARM MCUs (STM32F411), and I have been trying to find my way around the peripherals using STM's HAL library and STM32Cube.
I've already configured my board in order to use some peripherals:
Timer 2 for running an interrupt with a certain frequency
Timer 3 for running PWMs on 3 channels of it.
ADC with 4 channels, into DMA mode, for reading some analog input.
Let us suppose, now, that the PWM's whole period is 100 ms and its duty cycle is 50% (50 ms PWM on and 50 ms PWM off).
I would like to trigger an interrupt after a certain time of the PWM on level, let us say 50% of it.
Hence, I would like to run an interrupt at 25 ms in order to use the ADC for sampling it's analog inputs.
Do you have any suggestion on how could I implement such a kind of interrupt?
Thank you in advance for your help!
Since the ADC of the STM32F411 is used in Regular mode (not Injected mode) and only three channels out of four are used to generate PWM on Timer 3, the fourth channel can be used to trigger the ADC.
Hence Timer 3 is configured as follows:
CH1 used for Output Compare mode 0 (TIM3->CCMR1.OC1M = 0)
CH2, CH3, CH4 used for PWM outputs
Therefore TIM3->CCR1 is loaded to a value that gives 25% of duty, then it will generate TIM3_CH1 events that can be used to trigger ADC start-of-conversion at 25% of your TIM3 timebase.
I built this motor shield based on the L298N chip to control two motors of a tank. It uses pins 5 and 6 for one motor, and pins 10 and 11 for the other.
While trying to add a TSOP 4838 in order to control the tank with an IR remote I noticed that moving the motor on pins 10/11 in reverse only works at full speed - that is, a HIGH (255) value on pin 11. Anything below that value doesn't output anything on pin 11 (measured voltage on those pins is 0 V).
For the remote I use this library. The IR receiver is connected on pin 2 (but the pin doesn't matter). The problem is the library code itself. The line that enables IR listening irrecv.enableIRIn(); is what is causing the problem. I learned that there is a conflict of internal Arduino timers and the pins used for PWM by the shield.
This is the code to power the motor in reverse:
#include <IRremote.h>
// IR receiver configuration
const int irPin = 2;
IRrecv irrecv(irPin);
// Motors configuration
const int mLeftPin1 = 10;
const int mLeftPin2 = 11;
const int mRightPin1 = 5;
const int mRightPin2 = 6;
void setup()
{
// Start IR
irrecv.enableIRIn();
// Setup motors
pinMode(mLeftPin1, OUTPUT);
pinMode(mLeftPin2, OUTPUT);
pinMode(mRightPin1, OUTPUT);
pinMode(mRightPin2, OUTPUT);
// Move left motor in reverse, slower speed
analogWrite(mLeftPin2, 100); // This works only with 255 instead of 100
digitalWrite(mLeftPin1, LOW);
}
Now, I found here that the pins used by the timers on Arduino Uno are:
Pins 5 and 6: controlled by Timer0
Pins 9 and 10: controlled by Timer1
Pins 11 and 3: controlled by Timer2
So my questions are:
Why does the shield in the instructable use pins 10 and 11 for PWM ? They correspond to 2 different timers. Why not 9 and 10?
In order to use the IR along with the motor shield, what timer should I configure the IR library to use?
If the answer is 2, a line should be uncommented in IRremoteInt.h. I am guessing the Uno would take the else branch at line 68, although only timer1 and timer2 are there. I wonder why timer0 couldn't be used for the Uno.
Although I'd like to leave cutting traces and resoldering as a last option, another possibility would be to change the pins used by the shield, but which? And I am guessing this would also be paired with configuring the timers to PWM on other pins than default, but I don't know anything about timers/interrupts and my knowledge of Arduino and C is limited.
I made this a long question, because I want to learn not just solve the problem, so feel free to explain more than what is asked.
While looking up for a solution I also found other conflicts to keep in mind when using PWM or timers:
Timer0 is an 8-bit timer, it can hold a maximum value of 255. It is used by delay() and millis(), so there are consequences when messing with it
Timer1 is a 16-bit timer, it can hold a maximum of 65535 (an unsigned 16-bit integer). The Arduino Servo library uses this timer
Timer2 is an 8-bit timer used by the Arduino tone() function
And, of course, the IRremote library uses TIMER_RESET, so depending on which timer it uses it can conflict with the associated pins.
Not all hardware is designed in the best way. Using 10 and 11 is indeed wasteful because it requires two timers.
2/3. Ideally you will use a timer that is not Timer0. Here's some more details on timers/interrupts:
The Arduino chip (328P) has three timers. Each timer can be used for multiple uses, however it is important to note that you can only have one timer interrupt enabled for each timer.
Take Timer0 for example. It interrupts in order to generate the proper delays for the delay() and delay_us() methods. It also is used for the PWM outputs on pins 5 and 6. This can happen because the PWM outputs don't use a timer interrupt, they use separate output compare modules.
Now looking specifically at your problem, it should work fine, even though you have a PWM output using timer2, the PWM does not take an interrupt on timer2 so the IR library should be free to use that interrupt. However, looking into the IR library code, we see this piece of code:
ISR(TIMER_INTR_NAME)
{
TIMER_RESET;
It appears that every time it interrupts, it resets the timer count. This could be why your PWM output is not working properly. The output compare module is waiting for a certain tick count, and it never reaches that.
As to why it somehow works at 255, we can take a look at the analogWrite code:
void analogWrite(uint8_t pin, int val)
{
// We need to make sure the PWM output is enabled for those pins
// that support it, as we turn it off when digitally reading or
// writing with them. Also, make sure the pin is in output mode
// for consistenty with Wiring, which doesn't require a pinMode
// call for the analog output pins.
pinMode(pin, OUTPUT);
if (val == 0)
{
digitalWrite(pin, LOW);
}
else if (val == 255)
{
digitalWrite(pin, HIGH);
}
So by writing 255, the analogWrite code ignores the whole PWM and output compare thing, and just writes the pin high.
Finally, as to solving your problem, I would personally go the route of not using pins 11 and 3 (timer2). Yes it will require a small rewiring, but that way you can free up timer2 for the IR library to use.
Alternatively, you could poke around the IR library and try to make it work without resetting the count.
Pay attention to the board used, if you use Arduino Uno, then the code responsible would be: // Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
else
//define IR_USE_TIMER1 // tx = pin 9
define IR_USE_TIMER2 // tx = pin 3
endif
I had the same problem with a prebuilt L298 V2 motor shield.
The pins were marked like this on the shield:
Motor1: pin 3 and 5
Motor2: pin 6 and 9
I use PIN10 instead of 3 and using a small workaround: I put a wire from PIN10 to PIN3 on the SHIELD.
My project was to control my robot with a SAMSUNG TV remote control.
Im using Ethernut 2.1 B and I need a C program that outputs a clock signal at the timer 1 output B, with other words on output OCIB. The frequency of the clock signal should be at 1.0 kHz.
Anyone know how this could be done?
You need to look in COM bits for your timer. For instance, for Timer0 (8-bit), the COM bits are set in the TCCR0 register. Probably the setting you'd be interested in is
TCCR0 |= (0<<COM1)|1<<COM0); // Toggle OC0 on compare match
This will toggle the OC0 (pin14) line when timer reaches the specified value.
Which timer you use depends on the precision you need: obviosely the 16-bit timers can give you more precise time resolution then the 8-bit timers.
The setting of the registers for your specific frequency (1Khz) depends on the clock speed of your chip, and which timer you are using: the timers use a pre-scaled general clock signal (see table 56 of the datasheet for possible values). This means that the prescaler settings will depend on your clock speed, and how high you want to count. For most precision you will want to count as high as possible, which means the lowest possible prescaler setting compatible with your timer's maximum value.
As far as where to start, generally, reading the datasheet is a good place, but googling "AVR timer" can also be very helpful.
It seems to be based on the Atmel ATmega 128, so read that CPU's data sheet to figure out how to program the timer hardware.
Not sure if this microcontroller supports directly driving an output from a timer, if it doesn't you're going to have to do it in software from the interrupt service routine.
I've configured the timer 2 in CTC mode and to toggle the port pin on compare match (TCCR2A=0x42, TCCR2B=0x02, OCR2A=0x20) and have set DDR3 to output. Hence, according to the ATmega328P documentation (pages 158-163). OC2A (aka PB3) should toggle on each compare match. Unfortunately, I can't read the pin state at PORTB. Is this expected? I assumed, that even if a port is configured as output I can read the set value.
There were two problems:
In AVR Studio 4.18 I must not use the Simulator 1, because it has a bug for the timer 2 and hence can't toggle the port pin correctly. I needed to use Simulator 2 or AVR Studio 5.
I needed to read PINB instead of PORTB (though the toggling is an output operation).
I don't know about that specific microcontroller, but in some architectures you need at least a NOP between changing the port pin and the latch being updated (so you can read the change).
Also there is the maximum frequency a pin can be toggled at (many times slower than the microcontroller CPU clock). Be sure to not be over that frequency.