I am trying to use the Arduino time scheduler. I copied the code from here and I imported the library, but it didn't compile. Here's the compilation error code and the code itself:
Error:
In file included from time2.ino:1:
C:\arduino\arduino-1.0.3\libraries\Scheduler/Scheduler.h:62: error: 'byte' does not name a type
C:\arduino\arduino-1.0.3\libraries\Scheduler/Scheduler.h:64: error: 'NUMBER_OF_SCHEDULED_ACTIONS' was not declared in this scope
C:\arduino\arduino-1.0.3\libraries\Scheduler/Scheduler.h:65: error: 'byte' does not name a type
Code:
#include <Scheduler.h> // [url=http://playground.arduino.cc/uploads/Code/Scheduler.zip]Scheduler.zip[/url]
Scheduler scheduler = Scheduler(); //create a scheduler
const byte ledPin = 13; //LED on pin 13
void setup(){
Serial.begin(9600); //Iitialize the UART
pinMode(ledPin,OUTPUT); //set pin 13 to OUTPUT
}
void loop(){
scheduler.update(); //update the scheduler, maybe it is time to execute a function?
if (Serial.available()){ //if we have recieved anything on the Serial
scheduler.schedule(setHigh,500); //schedule a setHigh call in 500 milliseconds
Serial.flush(); //flush Serial so we do not schedule multiple setHigh calls
}
}
void setHigh(){
digitalWrite(ledPin,HIGH); //set ledPin HIGH
scheduler.schedule(setLow,500); //schedule setLow to execute in 500 milliseconds
}
void setLow(){
digitalWrite(ledPin,LOW); //set ledPin LOW
}
How can I fix this?
the library is not 1.0.0+ compliant.
Change replace the following .\Scheduler\Scheduler.h :
< #include <WProgram.h>
---
> #if defined(ARDUINO) && ARDUINO >= 100
> #include "Arduino.h"
> #else
> #include "WProgram.h"
> #endif
Then it will compile, for me at least.
Related
I am trying to make a Bluetooth speaker controlled by voice commands. I have successfully written code to connect to the speaker via Bluetooth. Then I have successfully trained a neural network and got the speaker to recognize my commands (Speaker has a microphone). I followed this tutorial and code: https://github.com/atomic14/voice-controlled-robot/tree/main/firmware.
However, when I try to combine the two codes together, I get a "could not allocate arena" error and the code doesn't run properly. All I did was add "#include <btAudio.h>", "btAudio audio = btAudio("ESP_Speaker");", and "audio.begin();" to the main file of the voice recognition code. I have attached code for the main file. All of the other files are pretty much unchanged. In addition, I've attached a picture of the output after the program uploads: Code output. Does anyone have an idea on how I should approach fixing this error? Thank you.
#include <Arduino.h>
#include <WiFi.h>
#include <driver/i2s.h>
#include <esp_task_wdt.h>
#include "I2SMicSampler.h"
#include "ADCSampler.h"
#include "config.h"
#include "CommandDetector.h"
#include "CommandProcessor.h"
#include <btAudio.h>
#include <stdint.h>
#include <esp_avrc_api.h>
btAudio audio = btAudio("ESP_Speaker");
// i2s config for using the internal ADC
i2s_config_t adcI2SConfig = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
.sample_rate = 16000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S_LSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 4,
.dma_buf_len = 64,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0};
// This task does all the heavy lifting for our application
void applicationTask(void *param)
{
CommandDetector *commandDetector = static_cast<CommandDetector *>(param);
const TickType_t xMaxBlockTime = pdMS_TO_TICKS(100);
while (true)
{
// wait for some audio samples to arrive
uint32_t ulNotificationValue = ulTaskNotifyTake(pdTRUE, xMaxBlockTime);
if (ulNotificationValue > 0)
{
commandDetector->run();
}
}
}
void setup()
{
Serial.begin(115200);
audio.begin();
delay(1000);
Serial.println("Starting up");
// make sure we don't get killed for our long running tasks
esp_task_wdt_init(10, false);
// start up the I2S input (from either an I2S microphone or Analogue microphone via the ADC)
#ifdef USE_I2S_MIC_INPUT
// Direct i2s input from INMP441 or the SPH0645
I2SSampler *i2s_sampler = new I2SMicSampler(i2s_mic_pins, false);
#else
// Use the internal ADC
I2SSampler *i2s_sampler = new ADCSampler(ADC_UNIT_1, ADC_MIC_CHANNEL);
#endif
// the command processor
CommandProcessor *command_processor = new CommandProcessor();
// create our application
CommandDetector *commandDetector = new CommandDetector(i2s_sampler, command_processor);
// set up the i2s sample writer task
TaskHandle_t applicationTaskHandle;
xTaskCreatePinnedToCore(applicationTask, "Command Detect", 8192, commandDetector, 1, &applicationTaskHandle, 0);
// start sampling from i2s device - use I2S_NUM_0 as that's the one that supports the internal ADC
#ifdef USE_I2S_MIC_INPUT
i2s_sampler->start(I2S_NUM_0, i2sMemsConfigBothChannels, applicationTaskHandle);
#else
i2s_sampler->start(I2S_NUM_0, adcI2SConfig, applicationTaskHandle);
#endif
}
void loop()
{
vTaskDelay(pdMS_TO_TICKS(1000));
}
I am trying to communicate with LCD2041 using I2C . I am using PIC32MM curiosity board . I wrote the following code on MP lab code configurator , but the status for I2c communications is stuck on I2C2_MESSAGE_PENDING . I need help on what I might have done wrong or what I am missing .
#include <stdint.h>
#include <string.h>
#include <xc.h>
#include "mcc_generated_files/mcc.h"
//#include "lcd_i2c.h"
#define slave_Adress 0b01010000
void ByteDelay(void){
// Delay between bytes required by LCD2041 spec
DELAY_microseconds(625);
}
void ReadDelay(void){
// Delay between read commands required by LCD2041 spec
DELAY_milliseconds(3);
}
void TransactionDelay(void){
// Delay between transactions required by LCD2041 spec
DELAY_microseconds(375);
}
int main(void)
{
SYSTEM_Initialize();
uint8_t data = 0xFE; // host to tell data are output via I2c
uint8_t lcd_clear_display = 0xA4; // command to clear LCD
TRISBbits.TRISB2 = 1; // set B2 (scl) as input
TRISBbits.TRISB3 = 1; // set B3 (SDA) as input
I2C2_Initialize() ;
I2C2_MESSAGE_STATUS status ;
I2C2_MasterWrite(data, 1 , slave_Adress, &status);
ByteDelay();
if ( status == I2C2_MESSAGE_PENDING) {led_3_SetHigh();}
return 1;
}
The default slave address for the LCD is 0x50
I had a similar error once with an pic18f and mcc. I forgot to activate the global interrups. I don't see a place where you do that in your code.
I'm using a Nucleo L496ZG, X-NUCLEO-IKS01A2 and the Quectel BG96 module to send sensor data (temperature, humidity etc..) to Azure IoT Central over HTTP.
I've been using the example implementation provided by Avnet here, which works fine but it's not power optimized and with a 6700mAh battery pack it only lasts around 30 hours sending telemetry ever ~10 seconds. Goal is for it to last around a week. I'm open to increasing the time between messages but I also want to save power in between sending.
I've gone over the Quectel BG96 manuals and I've tried two things:
1) powering off the device by driving the PWRKEY and turning it back on when I need to send a message
I've gotten this to work, kinda… until I get a hardfault exception which happens seemingly randomly anywhere from within ~5 minutes of running to 2 hours (messages successfully sending prior to the exception). Output of crash log parser is the same every time:
Crash location = strncmp [0x08038DF8] (based on PC value)
Caller location = _findenv_r [0x0804119D] (based on LR value)
Stack Pointer at the time of crash = [20008128]
Target and Fault Info:
Processor Arch: ARM-V7M or above
Processor Variant: C24
Forced exception, a fault with configurable priority has been escalated to HardFault
A precise data access error has occurred. Faulting address: 03060B30
The caller location traces back to my .map file and I don't know what to make of it.
My code:
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//#define USE_MQTT
#include <stdlib.h>
#include "mbed.h"
#include "iothubtransporthttp.h"
#include "iothub_client_core_common.h"
#include "iothub_client_ll.h"
#include "azure_c_shared_utility/platform.h"
#include "azure_c_shared_utility/agenttime.h"
#include "jsondecoder.h"
#include "bg96gps.hpp"
#include "azure_message_helper.h"
#define IOT_AGENT_OK CODEFIRST_OK
#include "azure_certs.h"
/* initialize the expansion board && sensors */
#include "XNucleoIKS01A2.h"
static HTS221Sensor *hum_temp;
static LSM6DSLSensor *acc_gyro;
static LPS22HBSensor *pressure;
static const char* connectionString = "xxx";
// to report F uncomment this #define CTOF(x) (((double)(x)*9/5)+32)
#define CTOF(x) (x)
Thread azure_client_thread(osPriorityNormal, 10*1024, NULL, "azure_client_thread");
static void azure_task(void);
EventFlags deleteOK;
size_t g_message_count_send_confirmations;
/* create the GPS elements for example program */
BG96Interface* bg96Interface;
//static int tilt_event;
// void mems_int1(void)
// {
// tilt_event++;
// }
void mems_init(void)
{
//acc_gyro->attach_int1_irq(&mems_int1); // Attach callback to LSM6DSL INT1
hum_temp->enable(); // Enable HTS221 enviromental sensor
pressure->enable(); // Enable barametric pressure sensor
acc_gyro->enable_x(); // Enable LSM6DSL accelerometer
//acc_gyro->enable_tilt_detection(); // Enable Tilt Detection
}
void powerUp(void) {
if (platform_init() != 0) {
printf("Error initializing the platform\r\n");
return;
}
bg96Interface = (BG96Interface*) easy_get_netif(true);
}
void BG96_Modem_PowerOFF(void)
{
DigitalOut BG96_RESET(D7);
DigitalOut BG96_PWRKEY(D10);
DigitalOut BG97_WAKE(D11);
BG96_RESET = 0;
BG96_PWRKEY = 0;
BG97_WAKE = 0;
wait_ms(300);
}
void powerDown(){
platform_deinit();
BG96_Modem_PowerOFF();
}
//
// The main routine simply prints a banner, initializes the system
// starts the worker threads and waits for a termination (join)
int main(void)
{
//printStartMessage();
XNucleoIKS01A2 *mems_expansion_board = XNucleoIKS01A2::instance(I2C_SDA, I2C_SCL, D4, D5);
hum_temp = mems_expansion_board->ht_sensor;
acc_gyro = mems_expansion_board->acc_gyro;
pressure = mems_expansion_board->pt_sensor;
azure_client_thread.start(azure_task);
azure_client_thread.join();
platform_deinit();
printf(" - - - - - - - ALL DONE - - - - - - - \n");
return 0;
}
static void send_confirm_callback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* userContextCallback)
{
//userContextCallback;
// When a message is sent this callback will get envoked
g_message_count_send_confirmations++;
deleteOK.set(0x1);
}
void sendMessage(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, char* buffer, size_t size)
{
IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray((const unsigned char*)buffer, size);
if (messageHandle == NULL) {
printf("unable to create a new IoTHubMessage\r\n");
return;
}
if (IoTHubClient_LL_SendEventAsync(iotHubClientHandle, messageHandle, send_confirm_callback, NULL) != IOTHUB_CLIENT_OK)
printf("FAILED to send! [RSSI=%d]\n", platform_RSSI());
else
printf("OK. [RSSI=%d]\n",platform_RSSI());
IoTHubMessage_Destroy(messageHandle);
}
void azure_task(void)
{
//bool tilt_detection_enabled=true;
float gtemp, ghumid, gpress;
int k;
int msg_sent=1;
while (true) {
powerUp();
mems_init();
/* Setup IoTHub client configuration */
IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle = IoTHubClient_LL_CreateFromConnectionString(connectionString, HTTP_Protocol);
if (iotHubClientHandle == NULL) {
printf("Failed on IoTHubClient_Create\r\n");
return;
}
// add the certificate information
if (IoTHubClient_LL_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK)
printf("failure to set option \"TrustedCerts\"\r\n");
#if MBED_CONF_APP_TELUSKIT == 1
if (IoTHubClient_LL_SetOption(iotHubClientHandle, "product_info", "TELUSIOTKIT") != IOTHUB_CLIENT_OK)
printf("failure to set option \"product_info\"\r\n");
#endif
// polls will happen effectively at ~10 seconds. The default value of minimumPollingTime is 25 minutes.
// For more information, see:
// https://azure.microsoft.com/documentation/articles/iot-hub-devguide/#messaging
unsigned int minimumPollingTime = 9;
if (IoTHubClient_LL_SetOption(iotHubClientHandle, "MinimumPollingTime", &minimumPollingTime) != IOTHUB_CLIENT_OK)
printf("failure to set option \"MinimumPollingTime\"\r\n");
IoTDevice* iotDev = (IoTDevice*)malloc(sizeof(IoTDevice));
if (iotDev == NULL) {
return;
}
setUpIotStruct(iotDev);
char* msg;
size_t msgSize;
hum_temp->get_temperature(>emp); // get Temp
hum_temp->get_humidity(&ghumid); // get Humidity
pressure->get_pressure(&gpress); // get pressure
iotDev->Temperature = CTOF(gtemp);
iotDev->Humidity = (int)ghumid;
iotDev->Pressure = (int)gpress;
printf("(%04d)",msg_sent++);
msg = makeMessage(iotDev);
msgSize = strlen(msg);
sendMessage(iotHubClientHandle, msg, msgSize);
free(msg);
iotDev->Tilt &= 0x2;
/* schedule IoTHubClient to send events/receive commands */
IOTHUB_CLIENT_STATUS status;
while ((IoTHubClient_LL_GetSendStatus(iotHubClientHandle, &status) == IOTHUB_CLIENT_OK) && (status == IOTHUB_CLIENT_SEND_STATUS_BUSY))
{
IoTHubClient_LL_DoWork(iotHubClientHandle);
ThisThread::sleep_for(100);
}
deleteOK.wait_all(0x1);
free(iotDev);
IoTHubClient_LL_Destroy(iotHubClientHandle);
powerDown();
ThisThread::sleep_for(300000);
}
return;
}
I know PSM is probably the way to go since powering on/off the device draws a lot of power but it would be useful if someone had an idea of what is happening here.
2) putting the device to PSM between sending messages
The BG96 library in the example code I'm using doesn't have a method to turn on PSM so I tried to implement my own. When I tried to run it, it basically runs into an exception right away so I know it's wrong (I'm very new to embedded development and have no prior experience with AT commands).
/** ----------------------------------------------------------
* this is a method provided by current library
* #brief Tx a string to the BG96 and wait for an OK response
* #param none
* #retval true if OK received, false otherwise
*/
bool BG96::tx2bg96(char* cmd) {
bool ok=false;
_bg96_mutex.lock();
ok=_parser.send(cmd) && _parser.recv("OK");
_bg96_mutex.unlock();
return ok;
}
/**
* method I created in an attempt to use PSM
*/
bool BG96::psm(void) {
return tx2bg96((char*)"AT+CPSMS=1,,,”00000100”,”00000001”");
}
Can someone tell me what I'm doing wrong and provide any guidance on how I can achieve my goal of having my device run on battery for longer?
Thank you!!
I got Power Saving Mode working by using Mbed's ATCmdParser and the AT+QPSMS commands as per Quectel's docs. The modem doesn't always go into power saving mode right away so that should be noted. I also found that I have to restart the modem afterwards or else I get weird behaviour. My code looks something like this:
bool BG96::psm(char* T3412, char* T3324) {
_bg96_mutex.lock();
if(_parser.send("AT+QPSMS=1,,,\"%s\",\"%s\"", T3412, T3324) && _parser.recv("OK")) {
_bg96_mutex.unlock();
}else {
_bg96_mutex.unlock();
return false;
}
return BG96Ready(); }//restarts modem
To send a message to Azure, the modem will need to be manually woken up by driving the PWRKEY to start bi-directional communication, and a new client handle needs to be created and torn down every time since Azure connection uses keepAlive and the modem will be unreachable when it's in PSM.
Can someone help me here to understand about arduino library variable name like what is tempTC, tempCJC, faultOpen, faultShortGND, faultShortVCC,
I am so confused. please help here ! thanks
/*
read_MAX31855.ino
TODO:
Clean up code and comment!!
Also make use of all library functions and make more robust.
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
http://creativecommons.org/licenses/by-sa/3.0/
*/
#include <MAX31855.h>
// Adruino 1.0 pre-defines these variables
#if ARDUINO < 100
int SCK = 13;
int MISO = 12;
int SS = 10;
#endif
int LED = 9;
// Setup the variables we are going to use.
double tempTC, tempCJC;
bool faultOpen, faultShortGND, faultShortVCC, x;
bool temp_unit = 1; // 0 = Celsius, 1 = Fahrenheit
// Init the MAX31855 library for the chip.
MAX31855 temp(SCK, SS, MISO);
void setup() {
Serial.begin(9600);
pinMode(LED, OUTPUT);
}
void loop() {
x = temp.readMAX31855(&tempTC, &tempCJC, &faultOpen, &faultShortGND, &faultShortVCC, temp_unit);
Serial.print(tempTC);
Serial.print("\t");
Serial.print(tempCJC);
Serial.print("\t");
Serial.print(faultOpen);
Serial.print(faultShortGND);
Serial.println(faultShortVCC);
digitalWrite(LED, HIGH);
delay(500);
digitalWrite(LED, LOW);
delay(500);
}
tempTC: The thermocouple value read from the IC.
tempCJC: The Cold Junction-Compensated temperature value.
faultOpen faultShortGND faultShortVCC: Flags that indicate wether any of these faults occurred while reading the temperature.
All these are done directly in the MAX31855 IC, read via SPI with the library you posted.
I have to make tasks as processes in Linux but I don't want the process to execute until all the processes are created. So I thought of moving the processes to wait queue soon after creation and wait until all processes are created.
#include <unistd.h> /* Symbolic Constants */
#include <sys/types.h> /* Primitive System Data Types */
#include <errno.h> /* Errors */
#include <stdio.h> /* Input/Output */
#include <stdlib.h> /* General Utilities */
#include <pthread.h> /* POSIX Threads */
#include <string.h> /* String handling */
#include <sched.h>
#include <linux/kernel.h>
#include <time.h>
#include <sys/resource.h>
#include <stddef.h>
#include <linux/sched.h>
#include <linux/wait.h> /* for wait_event_interruptible() & wake_up_interruptible() */
int done = 0;
static DECLARE_WAIT_QUEUE_HEAD(queue);
int main()
{
int pid1, pid2;
if ((pid1 = fork()) < 0) //create a child process
exit(1);
if ((pid2 = fork()) < 0) //create a child process
exit(1);
if (pid1 == 0) //child process
{
wait_event_interruptible(queue, done == 2);
printf("child 1\n");
}
else //parent process
{
done = done+1;
wake_up_interruptible(&queue);
}
if (pid2 == 0) //child process
{
wait_event_interruptible(queue, done == 2);
printf("child 2\n");
}
else //parent process
{
done = done+1;
wake_up_interruptible(&queue);
}
return 0;
}
But when I tried this sample code it shows these errors.
$ gcc -Wall try.c
try.c:18:8: warning: type defaults to ‘int’ in declaration of ‘DECLARE_WAIT_QUEUE_HEAD’ [-Wimplicit-int]
try.c:18:1: warning: parameter names (without types) in function declaration [enabled by default]
try.c: In function ‘main’:
try.c:33:6: warning: implicit declaration of function ‘wait_event_interruptible’ [-Wimplicit-function-declaration]
try.c:33:31: error: ‘queue’ undeclared (first use in this function)
try.c:33:31: note: each undeclared identifier is reported only once for each function it appears in
try.c:39:2: warning: implicit declaration of function ‘wake_up_interruptible’ [-Wimplicit-function-declaration]
try.c: At top level:
try.c:18:8: warning: ‘DECLARE_WAIT_QUEUE_HEAD’ declared ‘static’ but never defined [-Wunused-function]
When I checked $ man wait_event_interruptible, it says "No manual entry for wait_event_interruptible". So the API is missing in the library. How can I add it to the library? Thanks in advance.
wait_event_interruptible(), wake_up_interruptible() are some of the Kernel's API to create and use wait queues. You cannot use those from the user-land!
If I understand your purpose correctly, what you need to do is to create N processes barrier. If you know the number of the processes (N), you can easily use semaphores: initialize the semaphore with zero, all processes call down() and the last process calls up() N times. You can also use message queues.
You can also use the Linux API for barriers: pthread_barrier_wait and pthread_barrier_init, but I have not used this before.