I'm working on a project that involves switching the state of the Telosb, i would like to know how to put the motes to "sleep" (low power) and how to wake the motes up.
A mote will be automatically put to sleep (low-power) mode by TinyOS scheduler when the task queue is empty (so basically when there is nothing to do - no code to execute). The mote is waked up by an interrupt, for instance, timer interrupt (timer event occured), radio interrupt (radio packet has been received), or external IO pin interrupt (a user pressed a button).
However, microcontrollers have various low-power levels that differ in wake-up conditions, peripherals that can continue working, wake-up delay, and power consumption. Typically, in lower sleep levels, motes consume less power, but they can be woken up by only a few interrupts and most peripherals will stop operating. Sleep level is adjusted based on which peripherals are operating at the moment when the mote is about to sleep.
Sleep level can be overridden. This is what drivers do, providing the lowest acceptable sleep level based on their state. For example, if radio packet reception is requested, the radio driver may prevent from entering deepest sleep levels, because a packet would be lost in that case (that is, radio interrupt notifying about packet reception wouldn't wake the mote up). To override sleep level, your module has to implement interface PowerOverride, so that it returns the lowest acceptable sleep level at the time lowestState is called:
interface PowerOverride {
async command mcu_power_t lowestState();
}
PowerOverride must be then wired to the component McuSleepC:
component McuSleepC {
provides interface McuSleep;
provides interface PowerState;
uses interface PowerOverride;
}
mcu_power_t is a chip-specific type describing possible power levels. In case of TelosB, which is based on MSP430 microcontroller, this type is defined in tos/chips/msp430/msp430hardware.h:
enum {
MSP430_POWER_ACTIVE = 0,
MSP430_POWER_LPM0 = 1,
MSP430_POWER_LPM1 = 2,
MSP430_POWER_LPM2 = 3,
MSP430_POWER_LPM3 = 4,
MSP430_POWER_LPM4 = 5
};
The general conclusion is that if you only develop applications, you never have to worry about going to sleep or waking up.
See also: Microcontroller Power Management
Related
I am trying to measure power usage using dds353 kWh meter. This meter has a pulse output. I am interested in using the esp32 since I can periodically send the data over the internet to nodered dashboard.I am also very interested in using the esp32 in low power mode and periodically wake up to send data over mqtt. I have tried out examples from github using espressif idf but I would not mind an arduino equivalent. I would like to do hardware interrupt which when one of the rtc gpio pin goes high a counter is incremented while a seperate timer interrupt run and occasionally wakes up the main xtensia cores which fetches data from the rtc and sends it over. I have looked at the pulse counter examples and with my limited knowledge can not tell if the interrupts are triggered when the ulp is in sleep mode or only when it is on. I would really be glad if someone would show me how to basically use the ulp for counting pulses even when it is sleep mode and periodically wake up the main cores. I am ok with IDF or arduino examples
If you want to count pulses while in deep sleep youuse the ULP. Code on the ULP continues to execute when the board wakes up and goes to normal power mode. So when it is awake, it will still run the counter on the ULP processor unless you stop the ULP periodic wake up timer, ULP will keep waking up and running while the main CPU is active.
As you gave already checked with this example , it should be pretty close to what you need. The only difference seems to be that the example is set to wake up after a given number of pulses, rather than a fixed amount of time. However it should be easy to change that, by enabling deep sleep wake up from timer.For the Arduino you could check Some additional info:
ULP doesn't have GPIO interrupts. So you use deep sleep wake stub (small piece of code which runs immediately after deep sleep, prior to loading application from flash into RAM) you can increment the pulse counter variable, and go to sleep again. This way you can get low power consumption (~5uA) between pulses and moderate power consumption while running the wake stub (around 13mA), for a very short time.
So its up to you to experiment with your specific scenario.
You can use Pulse Counter(PCNT) feature in ESP32 to count the number of pulse in background, Understanding by using same you can able to do some periodic wake-up and read the count.. Its also possible to configure event when number of counts reached certain threshold and had lot of options,
For get information and available Interfaces and API's for Pulse Counter(PCNT) please follow below link, https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html
Initially I faced lot of issue to make Pulse Counter(PCNT) work in Adrino IDE for ESP-32, After multiple attempt I make it working, And same sample code is uploaded in GitHub for reference. I have not use all the API's in the official documentation but but used few of them and are working..
I have created sample program for a water flow meter, there also we use to get pulse which needs to count to measure the water flow rate, understanding simile to kWh meter.
GitHub Sample code Path:- https://github.com/Embedded-Linux-Developement/Arduino_Sample_Programs/tree/main/ESP_32/Water_Flow_Pulse_counter_WithOut_Interrupt_Using_PCNT
I have not placing the code here, because its there in GitHub and not directly for the asked question, but simile one and can use it. Its a working code I tested in HW.
Hopes Its helpful,
Regards, Jerry James
The Atmel SAMD21 TCC peripheral provides a STOP command, which pauses the counter. The counter can be resumed with a RETRIGGER command.
When STOP is issued, the TCC enters a fault state, in which the outputs are either tristated, or driven to states specified in a config register. Presumably this mechanism is designed to support a fixed failsafe output state.
In my case I want the output pins to freeze in the state they're in at the time of the STOP command. The only way I can see to to do this is to update the configured fault output state register every time the outputs are updated - requiring interrupt processing which kind of defeats the purpose of much of the TCC's output waveform extension architecture, as well as being a processing load I'd prefer to avoid. There are other complications too, such as accounting for the dead time mechanism, and hardware/software races.
So I've been looking at ways to achieve this that don't involve the STOP command - but I can't see any other way of stopping the counter. There's no way to gate the peripheral clock input, and disabling it in GCLK is ruled out as it also runs TCC1. (And who knows what other effects this would have.) Negating the ENABLE bit, besides being overkill, unsurprisingly also tristates the outputs. Modifying the configuration in various other ways usually requires writing to enable-protected registers, thus requiring disabling the peripheral first.
(One idea I haven't investigated that yet is to drive the counter from the event system, and control the event generation/gating instead.)
So: is there any way of pausing the peripheral in its current state, while maintaining the state of the output pins?
All that I can think of to try is the async 'COUNT' event, which sounds like it is a gate for the clock to the counter.
(page numbers from the 03/2016 manual)
31.6.4.3. Events, p.712;
Count during active state of an asynchronous event (increment or decrement, depending on counter direction). In this case, the counter will be incremented or decremented on each cycle of the prescaled clock, as long as the event is active.
31.8.9. Event Control, p.734;
EVCTRL register,
Bits 2:0 – EVACT0[2:0]: Timer/Counter Event Input 0 Action
0x5 COUNT (async) Count on active state of asynchronous event
The downside is that software events have to be synchronous.
THE GOAL
In my Qt application, I need to control a GPIO pin, depending on data being sent over the serial bus. So, I need to set it to HIGH for as long as I transmit data, and to LOW, immediately after the transmission ends. Consider it as a serial communication flow control pin, which when set to 1 it enables transmission, and when set to 0 enables receive of data. The entire system is half-duplex and communicates in a master-slave fashion.
THE PROBLEM
I managed to come close to a solution, by setting it to HIGH immediately before any transmission, introducing some constant delay (I used QThread:usleep() ) depending on the baud rate and then setting it to low again, but I was getting random "stretchings" of the pulse (staying HIGH longer than it should) when I was visualizing it with an oscilloscope.
ATTEMPTED SOLUTIONS
Well, it seems that some "magic" is taking place, which adds some extra delay, on top of the one I have manually defined. In order to get rid of that possibility, I used the bytesWritten() signal, so I can fire my setPinLow() slot when we finish writing the actual data to the port. So my code now looks like this:
classTTY::classTTY(/*someStuff*/) : port(/*some other stuff*/)
{
s_port = new QSerialPort();
connect(s_port, SIGNAL(bytesWritten(qint64)), this, SLOT(setPinLow()));
if(GPIOPin->open(QFile::ReadWrite | QFile::Truncate | QFile::Text | QFile::Unbuffered)) {
qDebug() << "GPIO pin ready to switch.";
} else {
qDebug() << "Failed to access GPIO pin";
}
bool classTTY::sendData(data, replyLength)
{
directionPinEnable(true);
if(m_port->isOpen()) {
s_expectedReplyLength = replyLength;
s_receivedData.clear();
s_port->flush();
s_port->write(data);
return true;
}
return false;
}
void classTTY::setPinLow()
{
gpioPinEnable(false);
}
void classTTY::gpioPinEnable(bool enable){
if(enable == true){
GPIOPin->write("1");
} else if (enable == false) {
GPIOPin->write("0");
}
}
After implementing it the pin started to give really short pulses, much more like "spikes", which implies (I think) that now it stays HIGH for as long as the Qt write() process lasts, and not while the actual propagation of the data lasts.
THE QUESTION(S)
What is that extra delay being added when I use the naive,
QThread::usleep approach, that causes the stretch of the pulse?
Why the signal-slot approach is not working, since it is
event-driven?
In general, how can I instruct the pin to go active ONLY during the
transmission of data and then drop again to zero, so I can receive
the slave's reply?
What is that extra delay being added when I use the naive, QThread::usleep approach, that causes the stretch of the pulse?
Linux is not a real-time operating system a thread sleep suspends the process fo no less than the time specified. During the sleep, other threads and processes may run and may not yield the processor for a longer time than your sleep period, or may not yield at all and consume their entire OS allocated time-slice. Beside that kernel driver interrupt handlers will always preempt a user-level process. Linus has a build option for real-time scheduling, but the guarantees remain less robust that a true RTOS and latencies typically worse.
Note also that not only can your thread be suspended for longer than the sleep period, but the transmission may be extended by more than the number of bits over baud-rate - the kernel driver can be preempted by other drivers and introduce inter-character gaps over which you have no control.
Why the signal-slot approach is not working, since it is event-driven?
The documentation for QSerialPort::waitForBytesWritten() states:
This function blocks until at least one byte has been written to the serial port and the bytesWritten() signal has been emitted.
So it is clear that the semantics of this are that "some data has been written" rather than "all data has been written". It will return whenever a byte is written, then if you call it again, it will likely return immediatly if bytes are continuing to be written (because QSerialPort is buffered and will write data independently of you application).
In general, how can I instruct the pin to go active ONLY during the transmission of data and then drop again to zero, so I can receive the slave's reply?
Qt is not unfortunately the answer; this behaviour needs to be implemented in the serial port kernel driver or at least at a lower-level that Qt. The Qt QSerialPort abstraction does not give you the level of control or insight into the actual occurrence "on the wire" that you need. It is somewhat arms-length from the hardware - for good reason.
However there is a simple solution - don't bother! it seems entirely unnecessary. It is a master-slave communication, and as such the data itself is flow control. The slave does not talk until spoken to, and the master must expect and wait for a reply after it has spoken. Why does the slave need any permission to speak other than that implied by being spoken to?
I have a PIC24 based system equipped with a 24 bit, 8 channels ADC (google MCP3914 Evaluation Board for more details...).
I have got the board to sample all of the 8 channels, store the data in a 512x8 buffer and transmit the data to PC using a USB module when the buffer is full (it's is done by different interrupts).
The only problem is that when the MCU is transmitting data (UART transmission interrupt has higher priority than the ADC reading interrupt) the ADC is not sampling data hence there will be data loss (sample rate is around 500 samples/sec).
Is there any way to prevent this data loss? maybe some multitasking?
Simply transmit the information to the UART register without using interrupts but by polling the bit TXIF
while (PIR1.TXIF == 0);
TXREG = "the data you want to send";
The same applies to the ADC conversion : if you were using interruptions to start / stop a conversion, simply poll the required bits (ADON) and thats it.
The TX bits and AD bits may vary depending on your PIC.
That prevents the MCU to enter an interrupt service routine and loose 3-4 samples.
In PIC24 an interrupt can be assigned one of the 8 priorities. Take a look at the corresponding section in the "Family Reference Manual" -> http://ww1.microchip.com/downloads/en/DeviceDoc/70000600d.pdf
Alternatively you can use DMA channels which are very handy. You can configure your ADC to use the DMA, and thus sampling and feeding the buffer won't use any CPU Time, same goes for UART I beleive.
http://ww1.microchip.com/downloads/en/DeviceDoc/39742A.pdf
http://esca.atomki.hu/PIC24/code_examples/docs/manuallyCreated/Appendix_H_ADC_with_DMA.pdf
Can someone explain me how to write ISR and how to set their priority when they are many in one program?
What is the function of vectors and is it necessary to consider them while interrupt handling?
If its possible please provide some examples as well (c code).
Just like when a doorbell or phone rings at your home you stop what you are doing, deal with the interrupt, then, ideally, return to what you were doing.
Same with a processor (msp430 or otherwise). There are ways to interrupt the processor for various reasons. I have a new byte in the uart for you, a timer has timed out, a gpio pin has changed state, etc. Things that you have configured to be something that interrupts the processor when they happen.
Just like the doorbell. the hardware has to have a way to stop and save something to remember what it was doing, find out what the interrupt is and handle it, then go back to what it was doing. Processors often, quite literally interrupt between instructions they will finish the current instruction (with piplines "current" is a bit fuzzy). Then based on the interrupt and the design of the processor there is some place that the hardware and software agree upon (the hardware dictates and the programmers use) such that the software can tell the processor where the code is that handles all interrupts or that particular flavor of interrupt, depending on how the processor is designed. A common solution is an interrupt vector table, a list of addresses usually that the programmer sets that point to the code that handles each one of those events or interrupts, both the programmer and the hardware know that a particular interrupt will cause a particular address to be read in the memory space and the hardware assumes that address is the code for that interupt.
So the processor gets an interrupt, it saves the state of the machine which at a minimum is the program counter and can depending on the design also save the status register and gprs, but often the programmer is responsible for saving gprs and such as needed. The hardware then based on the interrupt/event reads from an address, usually that address contains an address to a handler so for example 0xFFF8 might be the address to the interrupt handler (dont know didnt look it up for the msp430). so 0xFFF8 is not where the code is but the number at that address is where the code is maybe 0xD008 for example. It depends on the processor architecture but when you finish handling the interrupt you need to tell the processor so it can return to what was interrupted. often that is a special return from interrupt instruction but different processors have different solutions.
Priority if any, is dictated by the hardware design, something as simple as an msp430 might not (not sure off hand) have a priority scheme other than whoever gets here first. and the scheme might be that before you exit the handler you check to see if any others have come in while you were handling that one that interrupted you. if there is a priority scheme in the design then it simply repeats the process saves state (of the interrupt or forground code interrupted) finds the entry point for the handler using a vector table usually. when the highest priority handler finishes it returns and control goes back to the next higher priority thing, and eventually back to the forground task (assuming nothing else comes along).
in general an isr needs to not destroy anything the foreground task was using, preserve the state of the gprs if needed, preserve the state of the status register, dont mess up the stack or memory used by the foreground task, etc. And ideally keep the isr lean and mean, dont waste a lot of time there. the vector table is just where you fill in the addresses for entry points into the code reset handler interrupt handler, etc.
An interrupt handler (also known as an interrupt service routine or ISR) is a piece of code that runs when an event (I/O) occurs that requires CPU attention. An interrupt event is typically asynchronous, hence the reason a handler must be registered for the event.
For example, in the case of Serial communication, data is received by the USCI peripheral (configured for UART) that needs to be processed. In this case, an interrupt will be issued by the USCI peripheral and the CPU will begin executing from the interrupt handler (addressed by the interrupt vector). Vectors are at fixed locations and are outlined in the datasheet of your device. When the end of the interrupt handler is reached, the CPU will go back to where it left off (or service another interrupt). A datasheet/user's guide will explain the default priorities of interrupts.
A typical interrupt handler using the IAR Embedded Workbench IDE will look like the following:
// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
P1OUT ^= 0x01;
// P1.0 = toggle
P1IFG &= ~0x10;
// P1.4 IFG cleared
}
Further reading is available here.