So in my current RTOS code for mbed I have a timer that counts down from 3 minutes displayed in the format of minutes:seconds.I need to implement way so when the time gets to under a minute, the time is displayed in hundredths of a second, such as 59:59. How would I do that?
Here is my current code (the relevant code for displaying time is under void lcd_func (void const *args)):
#include "mbed.h"
#include "cmsis_os.h"
#include "scoreboard.h"
#define deb 180
C12832 lcd(p5, p7, p6, p8, p11);
LM75B sensor(p28,p27);
InterruptIn By1(p15); // Up on the Joystick
InterruptIn By2(p16); // Right on the Joystick
InterruptIn By3(p12); // Down on the Joystick
InterruptIn Team(p14); // Push on the Joystick
InterruptIn Play(p13); // Left to activate clock
// declaration of IDs handle for various threads
osThreadId score_ID, LCD_ID, time_ID, temp_ID;
// definition of the thread
osThreadDef(score_func, osPriorityNormal, DEFAULT_STACK_SIZE);
osThreadDef(lcd_func, osPriorityNormal, DEFAULT_STACK_SIZE);
osThreadDef(time_func, osPriorityNormal, DEFAULT_STACK_SIZE);
osThreadDef(temp_func, osPriorityNormal, DEFAULT_STACK_SIZE);
// message from ISrs
osMessageQDef(queue, 1, uint32_t);
osMessageQId(queue_ID);
// service routines for Joystick Up, Right and Down
void By1_isr() {osMessagePut(queue_ID, 1, 0);}
void By2_isr() {osMessagePut(queue_ID, 2, 0);}
void By3_isr() {osMessagePut(queue_ID, 3, 0);}
void Team_isr();
void Time_isr();
Timer t;
int minutes,seconds,zero,faults;
int main()
{
t.start();//start the timer
By1.rise(&By1_isr);
By2.rise(&By2_isr);
By3.rise(&By3_isr);
Team.rise(&Team_isr);
Play.rise(&Time_isr);
queue_ID = osMessageCreate(osMessageQ(queue), NULL);
score_ID = osThreadCreate(osThread(score_func), NULL);
LCD_ID = osThreadCreate(osThread(lcd_func), NULL);
time_ID = osThreadCreate(osThread(time_func), NULL);
temp_ID = osThreadCreate(osThread(temp_func), NULL);
}
void Team_isr()
{
if(t.read_ms() > deb) {
score.h0v1 = !score.h0v1;
osSignalSet(LCD_ID, 0x2);
t.reset();
}
}
void Time_isr()
{
if (score.running == 0)
{
score.running = 1;
}
else
{
faults++;
score.running = 0;
}
osSignalSet(time_ID, 0x3);
}
void Timer1_Update (void const *args)
{
score.time_count -= 1;
osSignalSet(LCD_ID, 0x2);
}
void Destroy(float val)
{
osThreadTerminate(time_ID);
osThreadTerminate(score_ID);
osThreadTerminate(LCD_ID);
lcd.cls();
lcd.locate(0,3);
lcd.printf("Gamed Terminated!\n");
lcd.printf("(temperature reached %2.1f)\n", val);
osThreadTerminate(temp_ID);
}
void score_func (void const *args)
{
score.h0v1 = 0; // home by default
score.time_count = 180;
score.home_count = 0;
score.visitors_count = 0;
uint32_t val;
while (1) {
osEvent score_sig = osMessageGet(queue_ID, osWaitForever);
if (score_sig.status == osEventMessage)
val = score_sig.value.v;
if (score.h0v1 == 0)
score.home_count += val;
else
score.visitors_count += val;
osSignalSet(LCD_ID, 0x2);
}
}
void lcd_func (void const *args)
{
while(1) {
minutes=score.time_count/60;
seconds=score.time_count%60;
if (seconds<10)
{
lcd.cls();
lcd.locate(0,3);
lcd.printf("Time remaining: %2d:%d%d\n",minutes,zero,seconds);
}
else{
lcd.cls();
lcd.locate(0,3);
lcd.printf("Time remaining: %2d:%2d\n",minutes,seconds);}
if (score.h0v1 == 0)
lcd.printf("*Home: %2d Visitors: %2d\n",
score.home_count, score.visitors_count);
else
lcd.printf(" Home: %2d *Visitors: %2d\n",
score.home_count, score.visitors_count);
osSignalWait(0x2, osWaitForever);
}
}
void time_func (void const *args)
{
osTimerDef (Timer1, Timer1_Update);
osTimerId Timer1_ID;
// Activate time
Timer1_ID = osTimerCreate (osTimer(Timer1), osTimerPeriodic, NULL);
while(1) {
osSignalWait(0x3, osWaitForever);
if (score.running == 0)
osTimerStop (Timer1_ID);
else
osTimerStart (Timer1_ID, 1000UL);
}
}
void temp_func (void const *args)
{
float temp;
if (sensor.open()) {
sensor.alertTemp(40.0);
while (1) {
temp = (float)sensor.temp();
if (temp > 30.0)
Destroy(temp);
osDelay(5000);
}
}
else
osThreadTerminate(temp_ID);
}
Change your timer to decrement every 100th and start at 18000. Then:
minutes = score.time_count / 6000;
seconds = (score.time_count % 6000) / 100 ;
hundredths = score.time_count % 100 ;
...
if( minutes == 0 )
{
lcd.printf( "Time remaining: 00:%2d:%2d\n", seconds, hundredths ) ;
}
else
{
lcd.printf( "Time remaining: %2d:%2d:00\n", minutes, seconds ) ;
}
Related
i am trying to make an alarm clock with esp8266 and ws2812b leds. On alarm time it must call the sunrise() function. The sunrise() function works fine when i put it directly in the loop function. But it doesn't work in alarm trigger.
if (AlarmData.AlarmOn[Current.Day])
{
if (!AlarmActive)//do not enter this routine if alarm already active
{
if (Current.Hour == AlarmData.Hour[Current.Day])
{
if (Current.Minute == AlarmData.Minute[Current.Day])
{
if (Current.Second > 0 && Current.Second < 3)
{
AlarmActive = true;
sunrise();
alarmTriggerTime = micros();
Serial.println("Its time for your alarm!");
}
}
}
}
}
My code is below. thanks in advance for your help
#include <ESP8266WiFi.h>
#include <ArduinoOTA.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include "EEPROMAnything.h"
#include "get_time.h"
#include "OTA.h"
#include <stdio.h>
#include <stdint.h>
#include "web_portal.h"
#include "ESP8266TimerInterrupt.h"
#include "restore_factory_settings.h"
#include "FastLED.h"
#define NUM_LEDS 60
#define DATA_PIN 5
// Define the array of leds
CRGB leds[NUM_LEDS];
#define timeZone 3
#define TenSecs 10000000
#define OneMin 60000000
#define TenMins 600000000
#define TIMER_INTERVAL_MS 1000
ESP8266Timer ITimer;
int timer;
int alarmTriggerTime;
struct CurrentTime Current;
bool AlarmActive;
struct AlarmDataStruct AlarmData;
int WiFiTimer;
char factory_settings_stored [3];
bool OneSecoundPassed;
void ICACHE_RAM_ATTR TimerHandler(void)
{
OneSecoundPassed = true;
}
void setup() {
Serial.begin(115200);
Serial.println("Booting");
EEPROM.begin(512);
EEPROM_readAnything(150, factory_settings_stored);
if (memcmp(&factory_settings_stored, "YES", 3) != 0)
{
restore_factory_settings();
}
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(0);
WiFi.mode(WIFI_STA);
WiFiManager wm;
bool response;
response = wm.autoConnect("AutoConnectAP"); // anonymous ap
if (!response) {
Serial.println("Failed to connect");
// ESP.restart();
}
else {
//if you get here you have connected to the WiFi
Serial.println("Lets Go");
}
start_server();
SetupOTA();
setup_time(timeZone);
Current = Current_Time();
EEPROM_readAnything(100, AlarmData);
Serial.print("Alarm set for ");
Serial.print(AlarmData.Hour[Current.Day]);
Serial.print(":");
Serial.println(AlarmData.Minute[Current.Day]);
timer = micros();
WiFiTimer = timer;
// Interval in microsecs
if (ITimer.attachInterruptInterval(TIMER_INTERVAL_MS * 1000, TimerHandler))
{
Serial.println("Starting ITimer OK, millis() = " + String(millis()));
}
else
{
Serial.println("Can't set ITimer correctly. Select another freq. or interval");
}
}
void loop() {
if (!AlarmActive)
{
ArduinoOTA.handle();
handle_client();
if ((micros() - WiFiTimer) > TenMins) // check if wifi connection lost and if so try to reconnect
{
if (WiFi.status() != WL_CONNECTED)
{
ESP.restart(); //try to reconnect rather than resetting
}
WiFiTimer = micros();
}
if (OneSecoundPassed)
{
updateLocalTime();
OneSecoundPassed = false;
}
//update current hour from NTP server
if ((micros() - timer) > TenMins)
{
Current = Current_Time();
timer = micros();
}
}
if (AlarmActive)
{
if ((micros() - alarmTriggerTime) > TenMins)
{
AlarmActive = false; //if alarm active for 10mins and no one switches it off then do it auto
}
}
if (AlarmData.AlarmOn[Current.Day])
{
if (!AlarmActive)//do not enter this routine if alarm already active
{
if (Current.Hour == AlarmData.Hour[Current.Day])
{
if (Current.Minute == AlarmData.Minute[Current.Day])
{
if (Current.Second > 0 && Current.Second < 3)
{
AlarmActive = true;
sunrise();
alarmTriggerTime = micros();
Serial.println("Its time for your alarm!");
}
}
}
}
}
else
{
if (!AlarmActive)
{
}
}
}
void updateLocalTime () {
Current.Second++;
if (Current.Second >= 60)
{
Current.Second = 0;
Current.Minute++;
if (Current.Minute >= 60)
{
Current.Minute = 0;
Current.Hour++;
if (Current.Hour >= 24)
{
Current.Hour = 0;
Current.Day++;
if (Current.Day >= 7)
{
Current.Day = 0;
}
}
}
}
char tempTime[6];
if (Current.Minute < 10 && Current.Second < 10)
{
sprintf(tempTime, "0%d:0%d", Current.Minute, Current.Second);
}
else if (Current.Minute < 10)
{
sprintf(tempTime, "0%d:%d", Current.Minute, Current.Second);
}
else if (Current.Second < 10)
{
sprintf(tempTime, "%d:0%d", Current.Minute, Current.Second);
}
else
{
sprintf(tempTime, "%d:%d", Current.Minute, Current.Second);
}
}
void sunrise() {
static const uint8_t sunriseLength = 30; //(min)
static const uint8_t interval = (sunriseLength * 60) / 256;
static const uint8_t binterval = (sunriseLength * 60) / 256;
// current gradient palette color index
static uint8_t heatIndex = 0; // start out at 0
static uint8_t brIndex = 0;
// HeatColors_p is a gradient palette built in to FastLED
// that fades from black to red, orange, yellow, white
// feel free to use another palette or define your own custom one
CRGB color = ColorFromPalette(HeatColors_p, heatIndex);
fill_solid(leds, NUM_LEDS, color); // fill the entire strip with the current color
EVERY_N_SECONDS(binterval) {
if (brIndex < 255) {
FastLED.setBrightness(brIndex);
brIndex++;
}
}
EVERY_N_SECONDS(interval) {
if (heatIndex < 255) {
heatIndex++;
}
}
FastLED.show();
}
Your sunrise function should be called over and over, every call changes the LED color a slight bit. This is why it works then you put it into the loop function.
However, you have guarded it so that it is specifically only called once - so now it is called, sets the LEDs to the dimmest setting possible, and is not called again.
What you need to do is separate this out into two parts: One that detects when to activate sunrise, and one that is continuously called when it is time. F.ex:
void loop()
{
/* stuff */
if (AlarmData.AlarmOn[Current.Day])
{
if (!AlarmActive) // do not enter this routine if alarm already active
{
if (Current.Hour == AlarmData.Hour[Current.Day])
{
if (Current.Minute == AlarmData.Minute[Current.Day])
{
if (Current.Second > 0 && Current.Second < 3)
{
AlarmActive = true;
alarmTriggerTime = micros();
Serial.println("Its time for your alarm!");
}
}
}
}
}
if (AlarmActive)
sunrise();
}
I have code to control the settings of and grab images from a Basler acA720-290gm camera. After a period of running, if the exposure time is changed, the Pylon::CBaslerUniversalInstantCamera.RetrieveResult call starts timing out and the camera becomes unresponsive to further requests to change the exposure time. The exposure time is not set to be large enough that it should be causing a timeout.
This is the heart of the code in question:
void process_pylon(Pylon::String_t serial_number, int64_t width, int64_t height, int64_t packet_size, int64_t inter_packet_delay) {
try {
Pylon::CBaslerUniversalInstantCamera camera;
Pylon::CTlFactory& tlFactory = Pylon::CTlFactory::GetInstance();
Pylon::CDeviceInfo info;
Pylon::DeviceInfoList_t filter;
info.SetSerialNumber(serial_number);
filter.push_back(info);
Pylon::DeviceInfoList_t devices;
while (1) {
try {
while (1) {
if (tlFactory.EnumerateDevices(devices, filter) > 0) {
g_print("The camera is connected.\n");
break;
}
else {
g_printerr("The camera is not connected.\n");
Pylon::WaitObject::Sleep(5000);
}
}
g_print("Attaching camera.\n");
camera.Attach(tlFactory.CreateFirstDevice(info));
g_print("Opening camera.\n");
camera.Open();
g_print("Setting width: %li\n", width);
camera.Width.TrySetValue(width);
g_print("Setting height: %li\n", height);
camera.Height.TrySetValue(height);
g_print("Setting GevSCPSPacketSize (packet size): %li\n", packet_size);
camera.GevSCPSPacketSize.TrySetValue(packet_size);
g_print("Setting GevSCPD (inter-packet delay): %li\n", inter_packet_delay);
camera.GevSCPD.TrySetValue(inter_packet_delay);
g_print("Starting grabbing.\n");
camera.StartGrabbing(Pylon::GrabStrategy_LatestImageOnly);
Pylon::CGrabResultPtr ptrGrabResult;
exposure_auto_set = 1;
exposure_time_raw_set = 1;
gain_auto_set = 1;
gain_raw_set = 1;
while (1) {
// Exposure Time
int32_t epics_exposure_auto_req = exposure_auto_req;
int32_t epics_exposure_auto_set = exposure_auto_set;
if (epics_exposure_auto_set > 0) {
g_print("Setting auto exposure: %i\n", epics_exposure_auto_req);
camera.ExposureAuto.SetIntValue((int64_t) epics_exposure_auto_req);
exposure_auto_set = 0;
}
exposure_auto = camera.ExposureAuto.GetIntValue();
int32_t epics_exposure_time_raw_req = exposure_time_raw_req;
int32_t epics_exposure_time_raw_set = exposure_time_raw_set;
if (epics_exposure_time_raw_set > 0) {
g_print("Setting exposure time: %i\n", epics_exposure_time_raw_req);
camera.ExposureTimeRaw.TrySetValue((int64_t) epics_exposure_time_raw_req, Pylon::IntegerValueCorrection_Nearest);
exposure_time_raw_set = 0;
}
exposure_time_raw = camera.ExposureTimeRaw.GetValue();
// Gain
int32_t epics_gain_auto_req = gain_auto_req;
int32_t epics_gain_auto_set = gain_auto_set;
if (epics_gain_auto_set > 0) {
g_print("Setting auto gain: %i\n", epics_gain_auto_req);
camera.GainAuto.SetIntValue((int64_t) epics_gain_auto_req);
gain_auto_set = 0;
}
gain_auto = camera.GainAuto.GetIntValue();
int32_t epics_gain_raw_req = gain_raw_req;
int32_t epics_gain_raw_set = gain_raw_set;
if (epics_gain_raw_set > 0) {
g_print("Setting gain: %i\n", epics_gain_raw_req);
camera.GainRaw.TrySetValue((int64_t) epics_gain_raw_req, Pylon::IntegerValueCorrection_Nearest);
gain_raw_set = 0;
}
gain_raw = camera.GainRaw.GetValue();
try {
camera.RetrieveResult((unsigned int) timeout_ms, ptrGrabResult, Pylon::TimeoutHandling_ThrowException);
if (ptrGrabResult->GrabSucceeded()) {
if (image_mutex.try_lock()) {
image.AttachGrabResultBuffer(ptrGrabResult);
image_mutex.unlock();
}
}
else {
g_printerr("The grab failed.\n");
g_printerr("%s\n", ptrGrabResult->GetErrorDescription().c_str());
}
}
catch (const Pylon::TimeoutException e) {
g_printerr("%s\n", e.GetDescription());
}
}
}
catch (const Pylon::GenericException& e) {
Pylon::WaitObject::Sleep(1000);
if (camera.IsCameraDeviceRemoved()) {
g_printerr("The connection to the camera has been lost.\n");
camera.DestroyDevice();
}
else {
g_printerr("%s\n", e.GetDescription());
}
}
}
}
catch (const Pylon::GenericException& e) {
g_printerr("An exception occurred.\n");
g_printerr("%s\n", e.GetDescription());
exit(-1);
}
}
#define CLK 2
#define DT 3
#define SW 4
#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>
LiquidCrystal_PCF8574 lcd(0x27);
int counter = 0;
int currentStateCLK;
int lastStateCLK;
int lastCLK,cnt=0,btnState,lastPress=0;
String currentDir ="";
unsigned long lastButtonPress = 0;
char *mainmenu[] ={"SET MODE","SET TEMP","SET HUMD","SERVO","RESET"};
char *setmode[] ={"INCUBATOR","HATCHER","BACK"};
void setup() {
// Set encoder pins as inputs
Wire.begin();
Wire.beginTransmission(0x27);
pinMode(CLK,INPUT);
pinMode(DT,INPUT);
pinMode(SW, INPUT_PULLUP);
lcd.begin(16, 2);
lcd.setBacklight(255);
lcd.home(); lcd.clear();
Serial.begin(9600);
lastStateCLK = digitalRead(CLK);
delay(100);
if(EEPROM_READ(0)==NULL){
SET_MODE();
}
Serial.print(EEPROM_READ(0));
}
void loop(){
disp();
rot();
}
void disp(){
lcd.setCursor(0,0);
lcd.print(" KGF");
}
void rot() {
int lim=sizeof(mainmenu)/2;
Serial.print(lim);
currentStateCLK = digitalRead(CLK);
if (currentStateCLK != lastStateCLK && currentStateCLK == 1){
lcd.clear();
lcd.setCursor(0, 1);
if (digitalRead(DT) != currentStateCLK) {
counter --;
if(counter<0){
counter=lim-1;
}
}
else {
// Encoder is rotating CW so increment
counter ++;
if(counter>lim-1){
counter=0;
}
lcd.print(mainmenu[counter]);
}
lastStateCLK = currentStateCLK;
int btnState = digitalRead(SW);
if (btnState == LOW) {
//if 50ms have passed since last LOW pulse, it means that the
//button has been pressed, released and pressed again
if (millis() - lastButtonPress > 50) {
if(counter==0){
SET_MODE();
}
}
}
lastButtonPress = millis();
}
delay(1);
}
void SET_MODE(){
int lim=sizeof(setmode)/2;
int currentCLK = digitalRead(CLK);
if (currentCLK != lastCLK && currentCLK == 1){
lcd.clear();
lcd.setCursor(0, 1);
if (digitalRead(DT) != currentCLK) {
cnt --;
if(cnt<0){
cnt=lim-1;
}
}
else {
// Encoder is rotating CW so increment
cnt ++;
if(cnt>lim-1){
cnt=0;
}
}
lcd.print(setmode[cnt]);
}
lastCLK = currentCLK;
btnState = digitalRead(SW);
if (btnState == LOW) {
//if 50ms have passed since last LOW pulse, it means that the
//button has been pressed, released and pressed again
if (millis() - lastButtonPress > 50) {
if(setmode[cnt]=="BACK"){
exit(0);
}
lcd.clear();
lcd.setCursor(0, 1);
EEPROM_WRITE(0,setmode[cnt]);
lcd.print("DONE");
}
lastPress = millis();
}
delay(1);
}
void EEPROM_WRITE(int addrOffset, const String &strToWrite)
{
byte len = strToWrite.length();
EEPROM.write(addrOffset, len);
for (int i = 0; i < len; i++)
{
EEPROM.write(addrOffset + 1 + i, strToWrite[i]);
}
}
String EEPROM_READ(int addrOffset)
{
int newStrLen = EEPROM.read(addrOffset);
char data[newStrLen + 1];
for (int i = 0; i < newStrLen; i++)
{
data[i] = EEPROM.read(addrOffset + 1 + i);
}
data[newStrLen] = '\0';
return String(data);
}
I want to call the SET_MODE() function in the loop from rot() function, I am building a menu based program so the SET MODE menu should redirect to the SET_MODE() function, and as I will be adding more menu and sub-menus how can I perform this task.
The SET_MODE() function doesn't work in loop I do not know why, it only works when I all it under void loop() directly.
I wrote a timer class for my project. I used standard C++ function calls for it.
I want to create a timer (start, stop, pause, continue, reset) it and also pass it new timings.
If the timer fires before I stop it, I want to get a qnx pulse message on a given channel.
This is the header:
#ifndef TIMER_H_
#define TIMER_H_
#include <time.h>
#include <sys/neutrino.h>
#include "HWaccess.h"
#include "address.h"
#define MILLISECONDS_NANOSECONDS_CONV 1000000
#define SECONDS_MILLISECONDS_CONV 1000
class Timer {
public:
/**
* Constructor creates a new timer, attaches to the given
* channel.
* Does not start timer!
*
* #param chid
* #param seconds
* #param milliseconds
* #param msg
*/
Timer(int chid, int sec, int msec, int msg);
/**
* Deletes timer after detach from channel
*/
virtual ~Timer();
/**
* Starts the timer
*/
void start();
/**
* Stops timer and resets it to initial values
*/
void stop();
/**
* Pauses the timer
*/
void pause();
/**
* Continues the timer
*/
void cont();
/**
* Resets the timer to initial values
*/
void reset();
/**
* Changes timer values to new given values and
* resets it
* Does not start the timer!
*
* #param seconds
* #param milliseconds
*/
void changeTime(int sec, int msec);
private:
/**
* Timer ID
*/
timer_t timerid;
/**
* Timerstruct for running timer
*/
struct itimerspec timer;
/**
* Timerstruct for backing up the running timer
*/
struct itimerspec backupTimer;
/**
* timer value: seconds
*/
int seconds;
/**
* timer value: milliseconds
*/
int miliSeconds;
/**
* Connection ID for timeout pulse
*/
int coid;
/**
* Event structure for timer if it fires
*/
struct sigevent event;
};
#endif /* TIMER_H_ */
...and the implementation:
#include "Timer.h"
Timer::Timer(int chid, int sec, int msec, int msg) {
if ((coid = ConnectAttach(0, 0, chid, _NTO_SIDE_CHANNEL, 0)) == -1) {
printf("Timer: Error in ConnectAttach\n");
}
SIGEV_PULSE_INIT(&event, coid, SIGEV_PULSE_PRIO_INHERIT, PULSE_FROM_TIMER, msg/*Timer abgelaufen*/);
if (timer_create(CLOCK_REALTIME, &event, &timerid) == -1) {
printf("Timer: Error in timer_create()\n");
}
seconds = sec;
miliSeconds = msec;
reset();
}
Timer::~Timer() {
if (ConnectDetach(coid) == -1) {
printf("Timer: Error in ConnectDetach\n");
}
if (timer_delete(timerid) == -1) {
printf("Timer: Error in timer_delete()\n");
}
}
void Timer::start() {
if(timer_settime(timerid, 0, &timer, NULL) == -1){
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::stop() {
// stop timer
timer.it_value.tv_sec = 0;
timer.it_value.tv_nsec = 0;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_nsec = 0;
if(timer_settime(timerid, 0, &timer, NULL) == -1){
printf("Timer: Error in timer_settime()\n");
}
// reset it
reset();
}
void Timer::pause() {
timer.it_value.tv_sec = 0;
timer.it_value.tv_nsec = 0;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_nsec = 0;
// backup running timer values
if(timer_gettime(timerid, &backupTimer) == -1){
printf("Timer: Error in timer_gettime()\n");
}
// disarm
if(timer_settime(timerid, 0, &timer, NULL) == -1){
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::cont() {
// recover old values
timer = backupTimer;
// Arm timer
if(timer_settime(timerid, 0, &timer, NULL) == -1) {
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::reset(){
timer.it_value.tv_sec = seconds;
timer.it_value.tv_nsec = miliSeconds * MILLISECONDS_NANOSECONDS_CONV;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_nsec = 0;
}
void Timer::changeTime(int sec, int msec){
seconds = sec;
miliSeconds = msec;
reset();
}
1) Can I set the timer struct's values to zero (to stop the timer) and backup the values in another back struct the way I am doing it? Or is the running timer decremented in the timer struct?
2) Can i easily restore the old timer values with a simple timer = backupTimer?
3) And finally, if I create and start a timer in a function, something like this:
void coolClass::interestingFunction() {
//do other time consuming stuff here...
Timer timer(chid, 10, 0);
timer.start();
}
... then the timer is created on the stack and when I exit this function (and its variables etc.) are no longer valid. Will the timer still count down and fire my pulse? Or will I have to use a classifier in my header file for this timer?
Ok i fixed all my problems ;>
if some1 is interested in how, heres the modified code:
#include "Timer.h"
Timer::Timer(int chid, int sec, int msec, int msg) {
if ((coid = ConnectAttach(0, 0, chid, _NTO_SIDE_CHANNEL, 0)) == -1) {
printf("Timer: Error in ConnectAttach\n");
}
SIGEV_PULSE_INIT(&event, coid, SIGEV_PULSE_PRIO_INHERIT, PULSE_FROM_TIMER, msg/*Timer abgelaufen*/);
if (timer_create(CLOCK_REALTIME, &event, &timerid) == -1) {
printf("Timer: Error in timer_create()\n");
}
seconds = sec;
miliSeconds = msec;
reset();
}
Timer::~Timer() {
if (ConnectDetach(coid) == -1) {
printf("Timer: Error in ConnectDetach\n");
}
if (timer_delete(timerid) == -1) {
printf("Timer: Error in timer_delete()\n");
}
}
void Timer::start() {
//TODO running flag, wg doppelt pause / continue
if(timer_settime(timerid, 0, &timer, NULL) == -1){
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::stop() {
// Stoppe den Timer
if(timer_settime(timerid, 0, NULL, NULL) == -1){
printf("Timer: Error in timer_settime()\n");
}
// Zuruecksetzen
reset();
}
void Timer::pause() {
// disarm (da erster Wert NULL)
if(timer_settime(timerid, 0, NULL, &backupTimer) == -1){
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::cont() {
// Arm, da Werte im struct wieder != 0
if(timer_settime(timerid, 0, &backupTimer, NULL) == -1) {
printf("Timer: Error in timer_settime()\n");
}
}
void Timer::reset(){
timer.it_value.tv_sec = seconds;
timer.it_value.tv_nsec = miliSeconds * MILLISECONDS_NANOSECONDS_CONV;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_nsec = 0;
}
void Timer::changeTime(int sec, int msec){
seconds = sec;
miliSeconds = msec;
reset();
}
I have an issue where my Arduino program hangs for no reason. I run my program, and at some undetermined point, the Serial Monitor stops printing output. Here's what I've tested so far:
In my "com.init_drone()" method, I've commented everything out except for the last line, which signals that the method returned. When I do this, my program hangs somewhere else but still it doesn't get to the infinite while loop.
I've been outputting memory usage, and I'm getting numbers no lower than 450 -- this tells me that I'm not using an absurd amount of memory.
I've tried removing the Timer1 instantiation, interrupt attach/detach, bu that has had no effect on the program.
My .ino file(and Command) is located here for anyone that wants a fuller picture and doesn't want to scroll through all this code I'm going to post below.
Here's my log output so far. Notice the truncation!:
AT&F
AT+NMAC=00:1d:c9:10:39:6f
AT+WM=0
AT+NDHCP=1
AT+WA=ardrone_279440
AT+NCUDP=192.168.1.1,5556
S0AT*CONFIG=1,"general:navdata_demo","TRUE"
EAT*CONFIG=1,"general:navdata_demo","TRUE"
638
S0AT*CONFIG=2,"control:altitude_max","2000"
EAT*CONFIG=2,"control:altitude_max","2000"
638
S0AT*CONFIG=3,"control:euler_angle_max","0.35"
EAT*CONFIG=3,"control:euler_angle_max","0.35"
586
S0AT*CONFIG=4,"control:outdoor","FALSE"
EAT*CONFIG=4,"control:outdoor","FALSE"
635
S0AT*CONFIG=5,"control:flight_without_shell","FALSE"
EAT*CONFIG=5,"control:flight_without_shell","FALSE"
574
S0AT*CTRL=6,4,0
EAT*CTRL=6,4,0
629
S0AT*CTRL=7,0,0
EAT*CTRL=7,0,0
629
S0AT*CTRL=8,4,0
EAT*CTRL=8,4,0
629
S0AT*COMWDG=9
EAT*COMWDG=9
629
S0AT*COMWDG=10
EAT*COMWDG=10
629
S0AT*COMWDG=11
EAT*COMWDG=11
629
S0AT*COMWDG=12
EAT*COMWDG=12
629
S0AT*COMWDG=13
EAT*COMWDG=13
629
S0AT*FTRIM=14
EAT*FTRIM=14
629
Here is my .ino file:
#include "Command.h"
#include "Streaming.h"
int debug = 1;
extern ring_buffer rx_buf;
extern resultint_ resultint;
Command com;
int sequenceNumber = 1;
String atcmd = "";
#include "TimerOne.h"
#define LEDpin 13
void setup()
{
PCsrl.begin(9600);
com.start_wifi_connection();
com.drone_is_init = com.init_drone();
Timer1.initialize(COMWDG_INTERVAL_USEC);
Timer1.attachInterrupt(watchdog_timer);
}
void watchdog_timer() {
com.sendwifi(com.makeComwdg());
}
void loop()
{
if (com.drone_is_init == 0) {
if (debug) {
// never use three ! together in arduino code
PCsrl.println("Drone wasn't initlized before loop() was called. Initalizing now.\r\n");
}
} else {
com.drone_takeoff();
com.drone_takeoff();
com.sendwifi(com.makePcmd(1,0,0,0,0));
com.sendwifi(com.makePcmd(1,0,0,0,0));
delay(5000);
com.moveForward(1);
com.moveRotate(180);
com.moveForward(1);
com.moveRotate(180);
delay(500);
com.drone_landing();
com.drone_landing();
delay(500);
//end of program
Timer1.detachInterrupt();
PCsrl.println("Program finished");
while (1){};
}
}
And my Command.cpp
#ifndef GAINSPAN
#define GAINSPAN
#include "Command.h"
extern int sequenceNumber;
extern int debug;
ring_buffer rx_buf= {{0}, 0, 0};
resultint_ resultint;
Command::Command()
{
at = "";
command = "";
s2ip_running = 0;
drone_is_init = 0;
drone_is_hover = 0;
emergency = 0;
}
void Command::sendwifi(String s) {
WIFIsrl.write(27); //esc
WIFIsrl.print("S0"); //choose connection CID 0
WIFIsrl.print(s);
WIFIsrl.write(27);
WIFIsrl.print("E");
if(debug) PCsrl.println(s);
WIFIsrl.println(memoryTest());
}
int Command::start_wifi_connection()
{
WIFIsrl.begin(9600);
WIFIsrl.println("");
WIFIsrl.println("AT&F");
//WIFIsrl.println("ATE0"); //turn off echo
WIFIsrl.print("AT+NMAC=00:1d:c9:10:39:6f\r"); //set MAC address
WIFIsrl.println("AT+WM=0");
WIFIsrl.println("AT+NDHCP=1");
/* drone's network profile, change if needed*/
WIFIsrl.println("AT+WA=ardrone_279440");
WIFIsrl.println("AT+NCUDP=192.168.1.1,5556");
readARsrl();
delay(3000); //need 3 seconds for connection to establish
return 0;
}
String Command::makeComwdg()
{
at = "AT*COMWDG=";
command = at + getSequenceNumber() + "\r\n";
return command;
}
void Command::sendComwdg_t(int msec)
{
for (int i = 0; i < msec; i+=20) {
sendwifi(makeComwdg());
delay(20);
}
}
void Command::sendFtrim()
{
at = "AT*FTRIM=";
command = at + getSequenceNumber() + "\r\n";
sendwifi(command);
}
void Command::sendConfig(String option, String value)
{
at = "AT*CONFIG=";
command = at + getSequenceNumber() + ",\"" + option + "\",\"" + value + "\"\r\n";
sendwifi(command);
}
void Command::sendRef(flying_status fs)
{
at = "AT*REF=";
if(fs == TAKEOFF){
command = at + getSequenceNumber() + ",290718208\r\n"; //takeoff
}
else if(fs == LANDING){
command = at + getSequenceNumber() + ",290717696\r\n"; //landing
} else if (fs == EMERGENCY_TOGGLE){
command = at + getSequenceNumber() + ",290717952\r\n"; //landing
}
// emergency -> 290717952
sendwifi(command);
}
void Command::send_control_commands(){
at = "AT*CTRL=";
sendwifi(at+getSequenceNumber()+",4,0\r\n");
sendwifi(at+getSequenceNumber()+",0,0\r\n");
sendwifi(at+getSequenceNumber()+",4,0\r\n");
}
void Command::drone_emergency_reset()
{
at = "AT*REF=";
command = at + getSequenceNumber() + ",290717952\r\n";
sendwifi(command);
}
/** Movement functions **/
int Command::moveForward(float distanceInMeters)
{
float i = 0;
String moveForward = makePcmd(1, 0, -.855, 0, 0);
delay(1000*distanceInMeters);
sendPcmd(moveForward);
return 1;
}
int Command::moveRotate(float yawInDegrees)
{
int i = 0;
while (i < yawInDegrees) {
String stayRotate = makePcmd(1, 0, 0, 0, 0.17);
sendPcmd(stayRotate);
delay(150);
i += 8;
}
return 1;
}
String Command::makePcmd(int enable, float roll, float pitch, float gaz, float yaw)
{
at = "AT*PCMD=";
command = at + getSequenceNumber() + "," + enable + "," + fl2int(roll) + "," + fl2int(pitch) + "," + fl2int(gaz) + "," + fl2int(yaw) + "\r";
return command;
}
void Command::sendPcmd(String command)
{
previousCommand = command;
sendwifi(command);
}
void Command::sendPcmd(int enable, float roll, float pitch, float gaz, float yaw)
{
at = "AT*PCMD=";
command = at + getSequenceNumber() + "," + enable + "," + fl2int(roll) + "," + fl2int(pitch) + "," + fl2int(gaz) + "," + fl2int(yaw) + "\r";
sendwifi(command);
}
String Command::makeAnim(anim_mayday_t anim, int time)
{
at = "AT*ANIM=";
command = at + getSequenceNumber() + "," + anim + "," + time + "\r\n";
return command;
}
void Command::doLEDAnim(int animseq, int duration)
{
PCsrl << "calling LEDAnim" << endl;
at = "AT*LED=";
command = at + getSequenceNumber() + "," + animseq + ",1073741824," + duration + "\r\n";
sendwifi(command);
}
int Command::start_s2ip()
{
char temp;
//delay(20000); //wait for drone to start
readARsrl();
if (debug) {
PCsrl << "trying to start s2ip" << endl;
}
ARsrl.print("\r\n");
delay(500);
ARsrl.print("\r\n");
delay(500);
ARsrl << "cd ~" << endl;
if (debug) {
readARsrl();
}
delay(500);
ARsrl << "cd data/video/apps/" << endl;
delay(500);
ARsrl << "./s2ip.arm" << endl;
while ((int) temp != 2) {
temp = ARsrl.read();
if (temp == 2) {
PCsrl << "s2ip is running" << endl;
ARsrl << "bullshit\r\n"; //to fix a delay bug
break;
}
//PCsrl << "s2ip not running" << endl;
}
if (debug) {
while (ARsrl.available()) {
PCsrl.write(ARsrl.read());
}
}
return 1;
}
void Command::quit_s2ip()
{
ARsrl.println("EXIT");
while (ARsrl.available()) {
PCsrl.write(ARsrl.read());
}
}
int Command::init_drone()
{
sendConfig("general:navdata_demo","TRUE");
sendConfig("control:altitude_max","2000");
sendConfig("control:euler_angle_max","0.35");
sendConfig("control:outdoor","FALSE");
sendConfig("control:flight_without_shell","FALSE");
send_control_commands();
sendComwdg_t(90);
sendFtrim();
drone_emergency_reset(); //clear emergency flag
return 1;
}
int Command::drone_takeoff()
{
sendRef(TAKEOFF);
int i = 0;
return 1;
}
int Command::drone_hover(int msec)
{
int i = 0;
while (i < msec) {
sendwifi(makePcmd(1, 0, 0, 0, 0));
delay(100);
i += 100;
}
return 1;
}
int Command::drone_landing()
{
sendRef(LANDING);
return 1;
}
int Command::drone_move_up(int centimeter)
{
int i = 0;
while (i < centimeter) {
ARsrl << makePcmd(1, 0, 0, 0.6, 0);
delay(100);
i += 10;
}
return 1;
}
int Command::drone_move_down(int centimeter)
{
int i = 0;
while (i < centimeter) {
sendwifi(makePcmd(1, 0, 0, -0.5, 0));
delay(100);
i += 10;
}
return 1;
}
long Command::fl2int(float value)
{
resultint.i = 0;
if (value < -1 || value > 1) {
resultint.f = 1;
} else {
resultint.f=value;
}
return resultint.i;
}
void Command::readARsrl()
{
while (ARsrl.available()) {
if (debug) {
PCsrl.write(ARsrl.read());
}
}
}
//Memory test code from : http://www.faludi.com/2007/04/18/arduino-available-memory-test/
int Command::memoryTest() {
int byteCounter = 0; // initialize a counter
byte *byteArray; // create a pointer to a byte array
// More on pointers here: http://en.wikipedia.org/wiki/Pointer#C_pointers
// use the malloc function to repeatedly attempt
// allocating a certain number of bytes to memory
// More on malloc here: http://en.wikipedia.org/wiki/Malloc
while ( (byteArray = (byte*) malloc (byteCounter * sizeof(byte))) != NULL ) {
byteCounter++; // if allocation was successful, then up the count for the next try
free(byteArray); // free memory after allocating it
}
free(byteArray); // also free memory after the function finishes
return byteCounter; // send back the highest number of bytes successfully allocated
}
int Command::getSequenceNumber(){
return sequenceNumber++;
}
// Volatile, since it is modified in an ISR.
volatile boolean inService = false;
void SrlRead()
{
if (inService) {
PCsrl.println("timer kicked too fast");
return;
}
interrupts();
inService = true;
while(ARsrl.available()) {
unsigned char k = ARsrl.read();
store_char(k, &rx_buf);
}
inService = false;
}
void read_rx_buf()
{
while (rx_buf.tail != rx_buf.head) {
if (debug) {
PCsrl.write(rx_buf.buffer[rx_buf.tail]);
}
rx_buf.tail = (unsigned int) (rx_buf.tail+ 1) % SERIAL_BUFFER_SIZE;
}
}
inline void store_char(unsigned char c, ring_buffer *buffer)
{
int i = (unsigned int)(buffer->head + 1) % SERIAL_BUFFER_SIZE;
// if we should be storing the received character into the location
// just before the tail (meaning that the head would advance to the
// current location of the tail), we're about to overflow the buffer
// and so we don't write the character or advance the head.
if (i != buffer->tail) {
buffer->buffer[buffer->head] = c;
buffer->head = i;
}
else {
Serial.println("ring buffer is too small");
}
}
#endif
I know it sounds weird but, sometimes this happens when arduino is not getting enough power supply. Try connecting the arduino to a power source different from USB.
As soon as I started to put things in prog memory my program started to clear up it's hiccups. It seems it was a memory issue.
I had the same problem, but the issue was with Timer1.initialize(). Try this:
com.drone_is_init = com.init_drone();
Serial.println("One");
Serial.println("Two");
Serial.println("Three");
Timer1.initialize(COMWDG_INTERVAL_USEC);
Timer1.attachInterrupt(watchdog_timer);
Open serial monitor and see... it will show until "Two", and then Arduino will hang.
The issue was I calling some functions of the LiquidCrystal_I2C library, that need interrupt routines. Check if your timer ISR is using some interrupts. If so, you should move this code to another place in your project.