Is there a way to calculate -time interval- using Esp32 timers? - timer

I want to calculate time interval with timers. I'm using arduino ide. Also i can not decide which library to useful.
I just tried something following code.
I'm using this library
#include <ESP32Time.h>
int a;
int b;
int ldrValue;
#define LDR 0
/* create a hardware timer */
hw_timer_t * timer = NULL;
int timeThatPast;
/* motor pin */
int motor = 14;
/* motor state */
volatile byte state = LOW;
void IRAM_ATTR onTimer(){
state = !state;
digitalWrite(motor, state);
}
void setup() {
Serial.begin(115200);
pinMode(motor, OUTPUT);
/* Use 1st timer of 4 */
/* 1 tick take 1/(80MHZ/80) = 1us so we set divider 80 and count up */
timer = timerBegin(0, 80, false);
/* Attach onTimer function to our timer */
timerAttachInterrupt(timer, &onTimer, true);
//********************ALARM*******************
/* Set alarm to call onTimer function every second 1 tick is 1us
=> 1 second is 1000000us */
/* Repeat the alarm (third parameter) */
timerAlarmWrite(timer, 7000000, false);
//********************************************
/* Start an alarm */
timerAlarmEnable(timer);
Serial.println("start timer");
}
void loop() {
int ldrValue = analogRead(LDR);
ldrValue = map(ldrValue, 0, 4095, 0, 10000);
if(ldrValue > 8500){
a = timerRead(timer);
digitalWrite(motor,HIGH);
while(1){
int ldrValue = analogRead(LDR);
ldrValue = map(ldrValue, 0, 4095, 0, 10000);
if(ldrValue < 8500){
b = timerRead(timer);
digitalWrite(motor,LOW);
Serial.print("Entering Loop");
Serial.println(a);
Serial.println("**********");
Serial.println("**********");
Serial.print("Exiting loop");
Serial.println(b);
int difference = b - a;
Serial.println("Difference");
Serial.println(difference);
break;
}
}
}
}

Use millis or micros if you need more precise timing.
Here is an example sketch:
long lastDoTime = 0;
void setup(){
Serial.begin(115200);
delay(1000);
Serial.println("Hello! We will do something at every ms");
}
void doThisAtEvery(int ms){
if( millis() - lastDoTime >= ms ){
// Must save the lastDoTime
lastDoTime = millis();
// Do some stuff at every ms
}
}
void loop(){
// It will do the thing in every 100 ms.
doThisAtEvery(100);
}
If you want to toggle a pin let's say every 100 microsec
long lastToggleTime = 0;
int motorPin = 14;
boolean lastPinState = LOW;
void setup(){
Serial.begin(115200);
}
void togglePinEvery(int micros){
if( micros() - lastToggleTime >= micros ){
lastToggleTime = micros();
digitalWrite(motorPin,!lastPinState);
lastPinState = !lastPinState;
}
}
void loop(){
togglePinEvery(100);
}
EDIT Since you wanted timers only.
Here is a detailed explanation about timers: https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
Code example:
volatile int interruptCounter;
int totalInterruptCounter;
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer() {
portENTER_CRITICAL_ISR(&timerMux);
interruptCounter++;
portEXIT_CRITICAL_ISR(&timerMux);
}
void setup() {
Serial.begin(115200);
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true);
timerAlarmEnable(timer);
}
void loop() {
if (interruptCounter > 0) {
portENTER_CRITICAL(&timerMux);
interruptCounter--;
portEXIT_CRITICAL(&timerMux);
totalInterruptCounter++;
Serial.print("An interrupt as occurred. Total number: ");
Serial.println(totalInterruptCounter);
}
}

Related

Esp32-(xQueueGenericReceive)- assert failed

I have been working on a project in which the analog values are sampled at a particular frequency and stored in an array. Then the value will be sent to user application ESP32 using BLE. But I got stuck in this error.
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1443
(xQueueGenericReceive)- assert failed! abort() was called at PC
0x4008e1d5 on core 1
Backtrace: 0x40091b38:0x3ffe0b20 0x40091d69:0x3ffe0b40
0x4008e1d5:0x3ffe0b60 0x400d1a2d:0x3ffe0ba0 0x4008e525:0x3ffe0be0
Rebooting... ets Jun 8 2016 00:22:57
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0,
SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1044
load:0x40078000,len:8896 load:0x40080400,len:5816 entry 0x400806ac
I am Using Esp32arduino and FreeRTOS for programming. The error is in the semaphore from the interrupt but I couldn't be able to find out exact solution. Please help me out guys.
#include <ArduinoJson.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#if CONFIG_FREERTOS_UNICORE
static const BaseType_t app_cpu = 0;
#else
static const BaseType_t app_cpu = 1;
#endif
//ADC Related Global Variables
static const uint16_t timer_divider = 80;
static const uint64_t timer_max_count = 1000;
static const int adc_pin = A0;
static const int BUF_SIZE = 1000;
static int buf[BUF_SIZE];
int Buff_Len = 0;
static int Read = 0;
static int Write = 0;
static int count = 0;
static float avg = 0;
int i = 0;
int BLE_flag = 0;
String cmd;
static hw_timer_t *timer = NULL;
static uint16_t val;
static int count1 = 0;
static SemaphoreHandle_t bin_sem = NULL;
static SemaphoreHandle_t bin_sem2 = NULL;
static portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
//ADC Related Global Variables
//BLE Global Variable
char Reading[4];
BLEServer *pServer = NULL;
BLECharacteristic *pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
//Declaration BLE necessary Classes
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
class MyServerCallbacks:public BLEServerCallbacks
{
void onConnect (BLEServer * pServer)
{
deviceConnected = true;
};
void onDisconnect (BLEServer * pServer)
{
deviceConnected = false;
}
};
//BLE Global Variables
//Task Section
void IRAM_ATTR onTimer ()
{
//sampling
xSemaphoreGiveFromISR (bin_sem2, &task_woken);
if (task_woken)
{
portYIELD_FROM_ISR ();
}
}
void move_to_Queue (void *parameters)
{
while (1)
{
xSemaphoreTake (bin_sem2, portMAX_DELAY);
if (Buff_Len == BUF_SIZE || count1 > 2000)
{
Serial.println ("Buffer is full");
xSemaphoreGive (bin_sem);
}
else
{
// storing the instantaneous sample value to buffer
}
}
}
void BLE_Task (void *parameters)
{
while (1) {
xSemaphoreTake (bin_sem, portMAX_DELAY);
Serial.println ("BLE");
// sending the data\lu
delay (10); // bluetooth stack will go into congestion, if too many packets are sent
}
}
Serial.println ();
}
}
void setup ()
{
// put your setup code here, to run once:
Serial.begin (115200);
vTaskDelay (1000 / portTICK_PERIOD_MS);
//BLE Declarations
BLEDevice::init ("UART Service");
pServer = BLEDevice::createServer ();
pServer->setCallbacks (new MyServerCallbacks ());
BLEService *pService = pServer->createService (SERVICE_UUID);
pTxCharacteristic = pService->createCharacteristic (CHARACTERISTIC_UUID_TX,
BLECharacteristic::
PROPERTY_NOTIFY);
pTxCharacteristic->addDescriptor (new BLE2902 ());
pService->start ();
pServer->getAdvertising ()->start ();
Serial.println ("Waiting a client connection to notify...");
//BLE Declaration
//ADC Semaphore and Timer Declarations
bin_sem = xSemaphoreCreateBinary ();
bin_sem2 = xSemaphoreCreateBinary ();
if (bin_sem == NULL || bin_sem2 == NULL)
{
Serial.println ("Could not create semaphore");
ESP.restart ();
}
xTaskCreatePinnedToCore (move_to_Queue,
"move_to_Queue", 1024, NULL, 2, NULL, app_cpu);
xTaskCreatePinnedToCore (BLE_Task,
"BLE_Task", 2048, NULL, 2, NULL, app_cpu);
timer = timerBegin (0, timer_divider, true);
// Provide ISR to timer (timer, function, edge)
timerAttachInterrupt (timer, &onTimer, true);
// At what count should ISR trigger (timer, count, autoreload)
timerAlarmWrite (timer, timer_max_count, true);
// Allow ISR to trigger
timerAlarmEnable (timer);
vTaskDelete (NULL);
}
void loop ()
{
// put your main code here, to run repeatedly:
}
`
Whole code: https://pastebin.com/K8ppkG28
Thanks in advance guys

Need to have 2 decimals in lcd.print

I have this program that prins to an LCD with watchdog interrupt. But the problem is that i need to have 2 decimals after seconds.
the code is as follows:
#include <Arduino.h>
#include "DFRobot_RGBLCD.h"
#include <stm32l4xx_hal_iwdg.h>
#include <Wire.h>
#define I2C2_SCL PB10
#define I2C2_SDA PB11
DFRobot_RGBLCD lcd(16,2);
TwoWire dev_i2c (I2C2_SDA, I2C2_SCL);
IWDG_HandleTypeDef watchdog;
void Start();
void Pause();
int paused = 0;
int milli = 0;
volatile byte state = HIGH;
void setup() {
pinMode(A2, INPUT_PULLUP);
pinMode(A3, INPUT_PULLUP);
lcd.init();
Serial.begin(9600);
dev_i2c.begin();
attachInterrupt(A2, Start, FALLING);
attachInterrupt(A3, Pause,RISING);
watchdog.Instance = IWDG;
watchdog.Init.Prescaler = IWDG_PRESCALER_256;
watchdog.Init.Reload = 1220;
watchdog.Init.Window = 0x0FFF;
HAL_IWDG_Init(&watchdog);
delay(1);
}
void loop() {
if(state){
delay(250);
lcd.setCursor(0, 0);
lcd.print("Sekunder: ");
lcd.print(millis()/1000-pause);
delay(100);
}
else{
delay(1000);
paused++;
HAL_IWDG_Refresh(&watchdog);
}
}
void Start(){
state = HIGH;
HAL_IWDG_Refresh(&watchdog);
delay(10);
}
void Pause(){
state = !state;
delay(10);
}
I have tried to put the -pause outside the lcd.print, but that didnt work. i've also tried this codeline: ```
lcd.print(millis()/1000.0, 2-paused);
But it seems like it takes -paused from the number 2. Do anyone have suggestion to how i can make it work so i get the 2 decimals?
String seconds = String(millis() / 1000.0, 2);
lcd.print(seconds);

STM32F407 Timer Interrupt

I working on STM32F4-Discovery with FreeRTOS v9. I have 2 tasks, task 1 is for blinking the LED, and task 2 I use for etherenet connection using LwIP.
Task 1
void test_print(void)
{
TickType_t wake_time,tamp1,tamp2;
const uint32_t period = 100;
char buff[32];
wake_time = xTaskGetTickCount();
while(1)
{
USART_puts("aaaaaaaaaaa\n ");
GPIO_SetBits(GPIOD,GPIO_Pin_13);
delay_dw(500); //This is just my own function delay
GPIO_ResetBits(GPIOD,GPIO_Pin_13);
delay_dw(500);
}
}
Task 2
void echo_tcp()
{
int c1,c2;
char clock[32],tmp[32];
tamp = 0;
while(1)
{
if(ETH_CheckFrameReceived())
{
cycle_start();
c1 = getCycles();
LwIP_Pkt_Handle();
c2 = getCycles();
cycle_stop();
tamp+= c2 - c1;
GPIO_SetBits(GPIOD,GPIO_Pin_12);
delay_dw(2000);
GPIO_ResetBits(GPIOD,GPIO_Pin_12);
delay_dw(2000);
}
else
{
GPIO_ResetBits(GPIOD,GPIO_Pin_12);
LwIP_Periodic_Handle(LocalTime);
}
}
}
I using a timer function for interrupt. The purpose of interrupt on this case is to show me about the cycle of the Task 2 every 1 second when I gives some connection load while 2 Tasks are running together.
This is my interrupt configuration
void TIM2_Config(){
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_PCLK1Config(RCC_HCLK_Div16);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_TimeBaseStructure.TIM_Prescaler = 42000-1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 200-1;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);
TIM_Cmd(TIM2,ENABLE);
}
void TIM_IT_Enable(){
TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE);
}
void NVIC_Config(){
NVIC_InitTypeDef NVIC_InitStrurture;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStrurture.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStrurture.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStrurture.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStrurture.NVIC_IRQChannelCmd =ENABLE;
NVIC_Init(&NVIC_InitStrurture);
}
int nInterrupt=0,counter;
char buffer[32];
char buf_temp[32];
void TIM2_IRQHandler(){
if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET){
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
nInterrupt++;
//USART_puts("Interrupt!!\n");
sprintf(buf_temp,"%d\n",temp); //tamp is int variable
USART_puts(buf_temp); //BUG IN HERE
temp = 0;
}
}
When I compile it and upload it on my STM32F4-Discovery all the tasks are not running, but when I command (disabled) the usart function on my TIM2_IRQHandler() function all the tasks are working well. If I do so, I can't see about the cycle of my Task. Anyone help please??
Sorry for bad English
Regards, Rama

pic32mx230 spi numbers of bytes

This one below i make new code for pic32mx230 SPI module harmony design i need to send 96 bytes
register values and every 3 bytes starting CS will Low to High can anyone help
us where i am wrong?
`APP_DATA appData;
static uint8_t __attribute__ ((aligned (8))) app_spi_tx_buffer[128] =0xD4,0x1E,
0x00
0xD4,0x1D,0x80,\
0xD4,0x1C,0x09,\
0xD4,0x1B,0x00,\
0xD4,0x1A,0x00,\
0xD4,0x19,0x64,\
0xD4,0x18,0x18,\
0xD4,0x17,0x00,\
0xD4,0x16,0x80,\
0xD4,0x15,0x00,\
0xD4,0x14,0x00,\
0xD4,0x13,0x00,\
0xD4,0x12,0x00,\
0xD4,0x11,0x00,\
0xD4,0x10,0x00,\
0xD4,0x0F,0x00,\
0xD4,0x0E,0x80,\
0xD4,0x0D,0xE8,\
0xD4,0x0C,0x18,\
0xD4,0x0B,0x00,\
0xD4,0x0A,0x01,\
0xD4,0x09,0xF0,\
0xD4,0x08,0x00,\
0xD4,0x07,0x00,\
0xD4,0x06,0x53,\
0xD4,0x05,0x00,\
0xD4,0x04,0x01,\
0xD4,0x03,0x04,\
0xD4,0x02,0xAA,\
0xD4,0x01,0xAA,\
0xD4,0x00,0xAB,\
0xD4,0x1B,0x00,\
0xD4,0x1D,0x81};
void Modulator_SPI_Enable ( void )
{
MOD_SPI_CS_SELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN); //start clock from here
TIME_DelayUs(1);
MOD_SPI_CS_DESELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN);
TIME_DelayUs(1);
MOD_SPI_CS_SELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN); //start clock from here
TIME_DelayUs(1);
MOD_SPI_CS_DESELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN);
TIME_DelayUs(1);
MOD_SPI_CS_SELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN);
TIME_DelayUs(1);
MOD_SPI_CS_DESELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN);
TIME_DelayUs(1);
MOD_SPI_CS_SELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN);
TIME_DelayUs(1);
MOD_SPI_CS_DESELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN);
TIME_DelayUs(1);
TIME_DelayMs(20);
}
/* state machine for the SPI */
static void SPI_Task(void)
{
unsigned char i;
/* run the state machine here for SPI */
switch (appData.spiStateMachine)
{
default:
case APP_SPI_STATE_START:
/* set the state to 'wait' early so that the interrupt doesn't
finish fast and write the state and then is overwritten */
appData.spiStateMachine = APP_SPI_STATE_WAIT;
MOD_SPI_CS_DESELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN); //start clock from here
for (i=0; i<3; i++)
{
app_spi_tx_buffer[i];
MOD_SPI_CS_SELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN);
}
appData.drvSPIBufferHandle = DRV_SPI_BufferAddWrite(appData.handleSPI0,
app_spi_tx_buffer, sizeof(app_spi_tx_buffer),
0, 0);
if (DRV_SPI_BUFFER_HANDLE_INVALID == appData.drvSPIBufferHandle)
{
/* try again if we get a bad handle */
appData.spiStateMachine = APP_SPI_STATE_START;
}
break;
case APP_SPI_STATE_WAIT:
{
if ( DRV_SPI_BufferStatus(appData.drvSPIBufferHandle) & DRV_SPI_BUFFER_EVENT_COMPLETE)
{
appData.spiStateMachine = APP_SPI_STATE_DONE;
}
}
break;
case APP_SPI_STATE_DONE:
break;
}
}
void APP_Initialize ( void )
{
/* Place the App state machine in its initial state. */
appData.state = APP_STATE_INIT;
Modulator_SPI_Enable();
MOD_SPI_CS_DESELECT(SPI_SLAVE_2_CS_PORT_ID,SPI_SLAVE_2_CS_PORT_PIN);
TXDIS_DSELECT();
MOD_SPI_CS_SELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN); // CS will be low
appData.handleSPI0 = DRV_HANDLE_INVALID;
/* TODO: Initialize your application's state machine and other
* parameters.
*/
}
void APP_Tasks ( void )
{
/* Check the application's current state. */
switch ( appData.state )
{
/* Application's initial state. */
case APP_STATE_INIT:
{
bool appInitialized = true;
if (DRV_HANDLE_INVALID == appData.handleSPI0)
{
appData.handleSPI0 = DRV_SPI_Open(0, DRV_IO_INTENT_WRITE);
appInitialized &= (DRV_HANDLE_INVALID != appData.handleSPI0);
}
if (appInitialized)
{
/* initialize the SPI state machine */
appData.spiStateMachine = APP_SPI_STATE_START;
appData.state = APP_STATE_SERVICE_TASKS;
}
break;
}
case APP_STATE_SERVICE_TASKS:
{
/* run the state machine for servicing the SPI */
SPI_Task();
break;
}
/* TODO: implement your application state machine.*/
/* The default state should never be executed. */
default:
{
/* TODO: Handle error in application's state machine. */
break;
}
}
}
Thanks
Nome
Sometimes the best answer is the simplest:
unsigned char buff={0xD4,0x04,0x03,0x02,0x01,0x1E};
unsigned char i;
SPI1CON = 0x8020; // SPI on and SPI Master see 61106G.pdf PIC32 FRM
for(i = 0; i < 6; i++)
{
/* CS = HIGH */
SPI1BUF=buff[i];
while(SPI1STATbits.SPIBUSY);
// read the SDI line
unsigned char x = SPI1BUF;
/* CS = LOW */
}
You'll need to choose the right SPIXCON for the SPI bus you are attached to in your schematic.
EDIT:
I will not do you project for you, here is my example with a bit more example code.
unsigned char buff[128]={0xD4,0x04,0x03,0x02,0x01,0x1E.....};
unsigned char i;
SPI1CON = 0x8020; // SPI on and SPI Master see 61106G.pdf PIC32 FRM
unsigned char j = 0;
for(i = 0; i < 128; i++)
{
/* CS = HIGH */
if (j == 0)
MOD_SPI_CS_DESELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN);
SPI1BUF=buff[i];
while(SPI1STATbits.SPIBUSY);
// read the SDI line
unsigned char x = SPI1BUF;
if ( j == 2)
{
j = 0;
MOD_SPI_CS_SELECT(SPI_SLAVE_1_CS_PORT_ID,SPI_SLAVE_1_CS_PORT_PIN);
}
else
j++;
/* CS = LOW */
}

How does delay work on the stm32l152RC?

I just bought an stm32l152RC and was wondering how the delay works.
The system clock is 16Mhz.
Code:
static volatile uint32_t TimingDelay;
void Delay(__IO uint32_t nCount);
int main(void) {
Config_Systick();
char *RCCp = (char*) 0x40023800;
int *PBp = (int *) 0x40020400;
// RCC Config
*((int*) (RCCp + 28)) |= 0x3f;
*((int*) (RCCp + 32)) |= 1;
*PBp = 0x5000;
while (1) {
GPIO_TOGGLE(GPIOB, LD_GREEN); //toggle green led
Delay(1000); // 1 second?
}
} // end of main
RCC_ClocksTypeDef RCC_Clocks;
void Config_Systick() {
RCC_GetClocksFreq(&RCC_Clocks);
SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); // setting changed to / 1000
}
void TimingDelay_Decrement(void) {
if (TimingDelay != 0x00) {
TimingDelay--;
}
}
void Delay(uint32_t nTime) {
TimingDelay = nTime;
while (TimingDelay != 0) {
};
}
When I execute Delay(1000); in this case the Delay is 1 second, could someone please explain why the delay is 1 second?
After doing some research this is the answer I came up with.
doing SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000); means you'r setting 1000 ticks per second. when you do Delay(100) the delay will be 100 ms.

Resources