I'm new to stm32 timers and have a question concerning triggering.
I would like to generate four squarewaves two of each complements of each other. That is the trivial part.
Now I would like to introduce a variable phaseshift between each of the two complementary signalgroups. (Phaseshift PWM)
Now my question, can I trigger timer 2 on the falling or rising edge of a pwm signal produced by timer 1?
Or is there another way for me to generate a phaseshift between those signals that's changeable during runtime?
A single advanced control timer (TIM1 or TIM8) can do all of this for you.
See the reference manual section 17.3.11 "Complementary outputs and dead-time insertion".
Alternatively you can chain timers, see section 13.3.15 of the same manual.
Related
I recently started experimenting with I2C-Hardware on my raspberry pi. Following this tutorial Using the I2C interface I already know how to read and set values. However, the program I want to realize needs the current value on a specific address all the time. So, I made a thread and query the value constantly in a never ending loop, which seems primitive to me. Is it possible to get notified in an event-like manner when a value on an I2C-adress changes?
A platform independend solution would also be much welcomed.
I was able to get what I wanted.
I use the following repeater for the I2C-Bus: link and it turns out there is a soldering bridge (LB2) you can set that sets a signal on GPIO17 whenever a value on the I2C-Bus changes since it has last been changed. I can now listen on this events accordingly.
Generally speaking, the I2C bus has no interrupt capability. So with only I2C, all you can do is poll the chip for a certain event to happen or value to change.
Most chips do have an interrupt line (sometimes even more than one) that can be programmed to trigger on certain events. The behavior of this line depends on the chip. Usually it needs to be enabled (using I2C commands) and it needs to be linked to a GPIO input line. For these, interrupt support is available.
I am working on Arduinos and I would like to use interrupts to use a rotary encoder. But I would like to reduce the interrupt code to the minimum.
Can I use multiple triggers on a single interrupt?
I would like to replcace my actual code :
attachInterrupt(0, ChangeA, CHANGE);
To something like
attachInterrupt(0, FailingA, FAILING);
attachInterrupt(0, RisingA, RISING);
Is it possible?
No, not exactly possible. The external interrupt is configured to react only to one of the possibilities internally.
One thing you can do is to use a CHANGE interrupt service routine and test the value of the pin at the beginning of the ISR to do FallingA() or RisingA().
There is a potential problem here. The pin may have changed again before you test it, so the interrupt that triggered the interrupt could have been falling, say, and your test determines that it was rising. One way to guard against two quick interrupts is to check if the flag is still set. It should have been cleared if at the start of the interrupt, and if it is set then a change happened again. There is no practical way to guard against three quick changes.
If you really want to use two separate ISRs, do you have an extra pin available? If so, you could just wire the pins together and run a FALLING ISR on one and a RISING ISR on the other.
I'm new to Arduino and coding, but have done all the tutorials and think I'm getting a grasp on how it all works.
I have a real-world problem that I'd love to solve with the arduino.
I have a PWM signal from a fuel injector on a gasoline engine that I need to derive two separate logical functions from inside the arduino.
Determine the delay between each rising edge (to derive engine RPM)
range between 6ms - 120ms between rising edges
and
read pulse-width Duty Cycle (to determine the fuel injector's duty cycle)
Pulsewidth range from 0.02ms to over 10ms for the pulse lengths.
these need to be represented independently in the logic as "RPM" and "Pulse Width"
I have read this blog about "secrets of Arduino PWM" and find it informative on how to WRITE pulse-width outputs of varying frequency and duty cycle, but I am trying to READ pulse-widths of varying frequency and duty cycle to create a variable byte or int to use for each.
Correct there is not a lot on timing pulse inputs or alike. Where the Arduino's ATmega can capture the timing of each side of the duty cycle by the below methods. And it will be up to the code to put them together and consider them a PWM for your needs.
There are several methods with examples.
Tight loop polling of the timed events. Such as with PulseIn
A better method is to create a timer1 overflow interrupt and
during that ISR pull the pin. This is the original method that Ken
Shirriff's Infrared Library works - 50ms pull shirriff IR Library where its resolution is only as good as the overflow.
Use Pin Change Interrupts ISR to get the time. Where it will be slightly latent. Where microtherion's fork of Ken's IR library converted the overflow to PinChangeInt. Where MicroTherion's code did this discretely in the library. Where the PinChangeInt library makes it simpler.
Use the Timer Input capture. In short when the corresponding
input pin changes the system clock is captured and an interrupt is
issued. So the ISR can latently get the exact time it occurred. InputCapture.ino
I just wrote a library with an example that does exactly this. In my Timer2_Counter library, I've written an example currently titled "read_PWM_pulses_on_ANY_pin_via_pin_change_interrupt" which reads in pulses then outputs the pulse width in us, with a resolution of 0.5us, as well as the period between pulses, and the frequency of the pulses.
Download the library and check out the example. To test the example you can connect a wire from a PWM pin outputting a PWM signal to the input pin. The library with example is found here: http://www.electricrcaircraftguy.com/2014/02/Timer2Counter-more-precise-Arduino-micros-function.html
PS. this example code uses pin change interrupts and can be done on ANY Arduino pin, including the analog pins.
Windows Embedded Compact 7.
Is there a way to test interrupt latency time from user space?
Are there any tools provided as part of platform builder?
I also saw a program called Intrtime.exe - but no examples on how to use it.
How does one test the interrupt latency time?
Reference for Intrtime.exe but how do I implement it?
http://www.ece.ufrgs.br/~cpereira/temporeal_pos/www/WindowsCE2RT.htm
EDIT
Also found:
ILTiming.exe Real-Time Measurement Tool (Compact 2013)
http://msdn.microsoft.com/en-us/library/ee483144.aspx
This really is a test that requires hardware, and there are a couple "latencies" you might measure. Once is the time from the interrupt signal to when the driver ISR reacts and the second is from when the interrupt occurs to when an IST reacts.
I did this back in the CE 3.0/CE 4.0 days by attaching a signal generator to an interruptable input an then having an ISR pulse a second input and an IST pulse a third input when they received the interrupt. I hooked a scope up to the input and outputs and used it to measure time between the input signal and output signals to get not just latency, but also jitter. You could easily add a 4th line for CE 7 so you could check an IST in user space and an IST in kernel space. I'd definitely be interested to see the results.
I don't think you can effectively measure this with software running on the platform, as you get into the problem of the code trying to do the measurement affecting the results. You're also talking time way, way below the system tick resolution so the scheduler is going to be problematic as well. CeLog might be able to get you an idea on these times, but getting it set up and running is probably more work than just hooking up a scope.
What is usually meant by interrupt latency is the time between an interrupt source asserting the interrupt line and a thread (sometimes in user-space) being scheduled and then executing as a result.
Unless your CPU has some accurate way of time-stamping interrupt events as they arrive at the CPU (rather than when an ISR runs), the only truly accurate measurement is one done externally - by measuring the time between a the interrupt line being asserted and some observable signal that the thread responding to the interrupt can control. A DSO or logic analyser is usually used for this purpose.
Software techniques usually rely on storing an accurate time-stamp at the earliest opportunity in an ISR. If you're certain the time between interrupt line becoming asserted and the ISR running is negligible, this might be valid. If, on the other hand, disabling of interrupts is being used to control concurrency, or interrupts are nested, you probably want to be measuring this as well.
I'm using the GCC compiler and C++ and I want to make a timer that triggers an interruption when the countdown is 0.
Any Ideas? Thanks in advance.
EDIT
Thanks to Adam, I know how to do it.
Now. What about multiple timers running in parallel?
Actually, these timers are for something very basic. In NCURSES, I have a list of things. When I press a key, one of the things will change colors for 5 seconds. If I press another key, another thing in the list will do the same. It's like emphasize strings depending on the user input. Is there a simpler way to do that?
An easy, portable way to implement an interrupt timer is using Boost.ASIO. Specifically, the boost::asio::deadline_timer class allows you to specify a time duration and an interrupt handler which will be executed asynchronously when the timer runs out.
See here for a quick tutorial and demonstration.
One way to do it is to use the alarm(2) system call to send a SIGALRM to your process when the timer runs out:
void sigalrm_handler(int sig)
{
// This gets called when the timer runs out. Try not to do too much here;
// the recommended practice is to set a flag (of type sig_atomic_t), and have
// code elsewhere check that flag (e.g. in the main loop of your program)
}
...
signal(SIGALRM, &sigalrm_handler); // set a signal handler
alarm(10); // set an alarm for 10 seconds from now
Take careful note of the cautions in the man page of alarm:
alarm() and setitimer() share the same timer; calls to one will interfere with use of the other.
sleep() may be implemented using SIGALRM; mixing calls to alarm() and sleep() is a bad idea.
Scheduling delays can, as ever, cause the execution of the process to be delayed by an arbitrary amount of time.