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);
}
}
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
I'm working in the communication of a PIC18F4550 and the PC with a pair of xBEE S2C. And
I am using xc8 to compile the code.
I send some characters to the PIC from the PC with an Xbee then I send a '/r', and the PIC has to return me the characters that I sent.
It works for 9 iterations, then it crashes. The image shows the
Serial Console (red characters are the response of the PIC).
I´ve tried resetting the EUSART but this doesn´t seem to work. Always fails at the 9th iteration. I´ve read some posts of OERR and I tried a lot of things but nothing has solved my problem.
EDIT: ***NOTE: This Error presents if the transmit interval of the package is
less than 1500 ms. And I need to transmit at least every 300ms.
Someone has an idea of what could it be?
Thanks
#define _XTAL_FREQ 8000000
volatile char bufferRx[60];
volatile char bufferTx[60];
volatile char dum;
int RxFlag,ContRx, ContTx;
void interrupt isr()
{
if(RCSTAbits.OERR)
{
RCSTAbits.CREN = 0;
RCSTAbits.CREN = 1;
}
x = RCREG;
if(x== 13)
{
bufferRx[ContRx] = x;
RxFlag=1;
}
else
{
bufferRx[ContRx] = x;
}
ContRx++;
}
void main(void)
{
//////////////////////////////////////////////////////////////////
//CONFIGURACIONES
//OSCILLATOR
OSCCONbits.IRCF= 0b111;
OSCCONbits.SCS=0b10;
//PORTS
PORTB = 0;
TRISB=1;
TRISC=0b10000000;
//INTERRUPTIONS
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
PIE1bits.RCIE=1;
PIE1bits.TXIE=0;
PIR1bits.RCIF=0;
//RCSTA TXSTA
RCSTAbits.SPEN=1;
RCSTAbits.RX9=0;
RCSTAbits.CREN=1;
TXSTAbits.BRGH=0;
TXSTAbits.SYNC=0;
TXSTAbits.TXEN = 1;
TXSTAbits.TX9=0;
//BAUDRATE BAUDCON
BAUDCONbits.ABDEN = 0;
BAUDCONbits.WUE = 0;
BAUDCONbits.TXCKP = 0;
BAUDCONbits.RXCKP = 0;
BAUDCONbits.BRG16=0;
SPBRG=51;
//////////////////////////////////////////////////////////////////
while(1)
{
while(RCSTAbits.FERR)
{
dum = RCREG;
}
if(RCSTAbits.OERR)
{
RCSTAbits.CREN = 0;
RCSTAbits.CREN = 1;
}
ContTx=0;
if(RxFlag==1)
{
for(int x=0;x<ContRx;x++)
{
bufferTx[x] = bufferRx[x];
TXREG=bufferTx[x];
while(TXSTAbits.TRMT==0);
{
__delay_ms(1);
bufferTx[x]= 00;
bufferRx[x]= 00;
}
ContTx++;
}
RxFlag=0;
ContRx=0;
}
}
}
You are not using the "volatile" keyword anywhere although you are modifying some globals inside the ISR and using them outside.
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 */
}
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.