Author Archives: baobab

[Arduino] Access the usb serial port on Ubuntu

You can do that by adding the pi user to the tty and dialout groups. You’ll need to do this before running the Arduino IDE.

sudo usermod -a -G tty pi
sudo usermod -a -G dialout pi

usermod: is a Linux program to manage users
-a -G: puts the user (pi) in the specified group (tty, then dialout)

Now you can run Arduino. Click Tools→Serial Port and select the serial port (most likely /dev/ttyACM0), then click Tools→Board select the type of Arduino Board you have (e.g. Uno)

[Arduino] Reset arduino in software

ref. http://www.instructables.com/id/two-ways-to-reset-arduino-in-software/

http://www.instructables.com/id/two-ways-to-reset-arduino-in-software/step2/using-just-software/

reset function at address 0:

void(* resetFunc) (void) = 0;//declare reset function at address 0

void loop(){
...
   if(isReset) {
      isReset = false;
      resetFunc();
   }
}



Using 1 wire connected to the RESET pin:

int resetPin = 12;
void setup(){
  digitalWrite(resetPin, HIGH);
  pinMode(resetPin, OUTPUT);
  ....
}

void loop(){
 ....
  //Resetting
  digitalWrite(resetPin, LOW);
  ....
}

Software Reset:

#include <avr/wdt.h> //watchdog timer
//software reset
#define soft_reset()        \
do                          \
{                           \
    wdt_enable(WDTO_15MS);  \
    for(;;)                 \
    {                       \
    }                       \
} while(0)

void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
  asm volatile ("  jmp 0");  
}  

void (softReset)(void){
  asm volatile ("  jmp 0");
}

void reboot() {
  wdt_disable();  
  wdt_enable(WDTO_15MS);
  while (1) {}
}

[ubuntu] How to find the MAC address of a remote computer?

$ ping 192.168.0.3

$ arp -a

PING the target machine so you have made contact with it and then issue the command arp -a to view your local arp table, which will list IP addresses and their corresponding MAC addresses eg:

 arp - manipulate the system ARP cache

SYNOPSIS
       arp [-vn] [-H type] [-i if] [-a] [hostname]

       arp [-v] [-i if] -d hostname [pub]

       arp [-v] [-H type] [-i if] -s hostname hw_addr [temp]

       arp [-v] [-H type] [-i if] -s hostname hw_addr [netmask nm] pub

       arp [-v] [-H type] [-i if] -Ds hostname ifname [netmask nm] pub

       arp [-vnD] [-H type] [-i if] -f [filename]

DESCRIPTION
       Arp  manipulates or displays the kernel's IPv4 network neighbour cache. It can add entries to the table, delete one or display the current
       content.

       ARP stands for Address Resolution Protocol, which is used to find the media access control address of a network neighbour for a given IPv4
       Address.

[Arduino Wifi shield] How to upgrade Wifi shield firmware on Ubuntu

ref. http://flashgamer.com/arduino/comments/how-to-update-the-official-arduino-wifi-shield
http://arduino.cc/en/Hacking/WiFiShieldFirmwareUpgrading

Hardware: Arduino UNO rev.3, Arduino Wifi shield, usb mini cable

1. Install dfu-programmer

sudo apt-get install dfu-programmer

2. Download latest Wifi shield firmware

https://github.com/arduino/Arduino/tree/master/hardware/arduino/firmwares
또는, Aduino IDE software 에 포함된 Wifi shield 펌웨어 사용.
arduino-nightly/hardware/arduino/avr/firmwares/wifishield/binary/

3. Wifi shield 의 Power 핀과 Analog 핀 사이에 있는 점퍼 둘을 연결함

4. ArduinoWifiShield_upgrade.sh 스크립트를 실행

$ cd arduino-nightly/hardware/arduino/avr/firmwares/wifishield/scripts
–> ArduinoWifiShield_upgrade.sh 파일에서 경로수정
$ vi ArduinoWifiShield_upgrade.sh
# WIFI_FW_PATH=”/hardware/arduino/firmwares/wifishield/binary”
WIFI_FW_PATH=”/hardware/arduino/avr/firmwares/wifishield/binary”

$ sudo chmod a+x ArduinoWifiShield_upgrade.sh

- 스크립트 파일 도움말:
$ sudo ./ArduinoWifiShield_upgrade.sh -h

- 스크립트 파일 실행:
–> 옵션:
-a : Arduino IDE 설치 경로
-f : shield (Arduino WiFi Shield upgrade), all (Arduino WiFi Shield upgrade, HD WiFi module firmware)

sudo ./ArduinoWifiShield_upgrade.sh -a /home/jinny/App/arduino-nightly -f all

       Arduino WiFi Shield upgrade
=========================================
Instructions:

To access to the USB devices correctly, the dfu-programmer needs to have the root permissions.

You can upgrade the firmware of the antenna togheter with the shield firmware or only the shield firmware
if there aren't changes on the antenna firmware.

Use the '-h' parameter for help
=========================================

****Upgrade HD WiFi module firmware****

Validating...
167732 bytes used (66.05%)

Press the RESET button on the shield then type [ENTER] to upgrade the firmware of the shield..

****Upgrade WiFi Shield firmware****

Validating...
261594 bytes used (103.01%)

Done. Remove the J3 jumper and press the RESET button on the shield.
Thank you!

5. 점퍼를 연결한 핀을 제거하고 Reset 버튼을 누룸.

[Arduino] Single, double and hold button

ref. http://arduino.cc/forum/index.php/topic,42489.0.html

 

const int button = 3;
const int led = 13;

int bounceTime = 50;
int holdTime = 250;
int doubleTime = 500;

int lastReading = LOW;
int hold = 0;
int single = 0;
int LEDstate = 0;

long onTime = 0;
long lastSwitchTime = 0;

void setup() {
  pinMode(button, INPUT);
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
  Serial.begin(9600);
}

void loop() {

  int reading = digitalRead(button);

//first pressed
  if (reading == HIGH && lastReading == LOW) {
    onTime = millis();
  }

//held
  if (reading == HIGH && lastReading == HIGH) {
    if ((millis() - onTime) > holdTime) {
      invertLED();  
      hold = 1;
    }
  }

//released
  if (reading == LOW && lastReading == HIGH) {
    if (((millis() - onTime) > bounceTime) && hold != 1) {
      onRelease();
    }
    if (hold == 1) {
      Serial.println("held");
      digitalWrite(led, LEDstate);
      hold = 0;
    }   
  }
  lastReading = reading;

  if (single == 1 && (millis() - lastSwitchTime) > doubleTime) {
    Serial.println("single press");
    single = 0;
  }

}

void onRelease() {

  if ((millis() - lastSwitchTime) >= doubleTime) {
    single = 1;
    lastSwitchTime = millis();
    return;
  }  

  if ((millis() - lastSwitchTime) < doubleTime) {
    toggleLED();
    Serial.println("double press");
    single = 0;
    lastSwitchTime = millis();
  }  

}

void toggleLED() {
  if (LEDstate == 0) {
    LEDstate = 1;
  } else {
    LEDstate = 0;
  }
  digitalWrite(led, LEDstate);  
} 

void invertLED() {
  if (LEDstate == 0) {
  digitalWrite(led, 1);
  } else {
  digitalWrite(led, 0);
  }
}

ref. http://www.arduino.cc/playground/Code/Button
Arduino Button libraries 에
onPress(), onDoubleClick(), isHold() 메소드가 있지만
아직은 불안전하다.

 

[Arduino] Modified TimeAlarms callback function with parameter

Attachment:
TimeAlarms2

TimeAlarms2Example.ino

/*
 * This example calls alarm functions at 8:30 am and at 5:45 pm (17:45)
 * and simulates turning lights on at night and off in the morning
 * A weekly timer is set for Saturdays at 8:30:30
 *
 * A timer is called every 15 seconds
 * Another timer is called once only after 10 seconds
 *
 * At startup the time is set to Jan 1 2011  8:29 am
 */

#include <Time.h>
#include <TimeAlarms2.h>

typedef struct StoreStruct {
  short duration, pin;
} Storage;
Storage storage;


void setup()
{
  Serial.begin(9600);
  setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011
  
  storage.duration = 60; //second
  storage.pin = 13; //pin number
  // create the alarms 
  Alarm.alarmRepeat(8,30,0, MorningAlarm, &storage);  // 8:30am every day, 60 sec duration
  Alarm.alarmRepeat(17,45,0,EveningAlarm, &storage);  // 5:45pm every day, 60 sec duration
  Alarm.alarmRepeat(dowSaturday,8,30,30,WeeklyAlarm, &storage);  // 8:30:30 every Saturday, 60 sec duration

  Alarm.timerRepeat(15, Repeats, NULL);            // timer for every 15 seconds    
  Alarm.timerOnce(10, OnceOnly, &storage);             // called once after 10 seconds, duration of 60 sec 
 }
 
void  loop(){  
  digitalClockDisplay();
  Alarm.delay(1000); // wait one second between clock display
}

// functions to be called when an alarm triggers:

void MorningAlarm(void * pStorage){
  Serial.println("Alarm: - turn lights on and off");  
  int pin = ((Storage *)pStorage)->pin;
  int duration = ((Storage *)pStorage)->duration;
  pinMode( pin, OUTPUT);
  digitalWrite( pin, HIGH);
  Alarm.timerOnce(duration, setLow, pStorage);
}

void EveningAlarm(void * pStorage){
  Serial.println("Alarm: - turn lights on and off");
  int pin = ((Storage *)pStorage)->pin;
  int duration = ((Storage *)pStorage)->duration;
  pinMode( pin, OUTPUT);
  digitalWrite( pin, HIGH);
  Alarm.timerOnce(duration, setLow, pStorage);
  
}

void WeeklyAlarm(void * pStorage){
  Serial.println("Alarm: - its Saturday Morning");
  int pin = ((Storage *)pStorage)->pin;
  int duration = ((Storage *)pStorage)->duration;
  pinMode( pin, OUTPUT);
  digitalWrite( pin, HIGH);
  Alarm.timerOnce(duration, setLow, pStorage);
  
}

void setLow(void * pUserData){
  Storage * pStorage = (Storage *)pUserData;
  Serial.println("setLow calling...");
  pinMode(pStorage->pin, OUTPUT);
  digitalWrite(pStorage->pin, LOW);
}

void Repeats(void * pStorage){
  Serial.println("15 second timer");         
}

void OnceOnly(void * pStorage){
  Serial.println("This timer only triggers once");  
  Serial.print("pin: "); Serial.println(((Storage *)pStorage)->pin);
  Serial.print("duration: "); Serial.println(((Storage *)pStorage)->duration);
  
}

void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
}

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

TimeAlarms2.h

//  TimeAlarms.h - Arduino Time alarms header for use with Time library

#ifndef TimeAlarms2_h
#define TimeAlarms2_h

#include <inttypes.h>

#include "Time.h"

#define dtNBR_ALARMS 6   // max is 255

#define USE_SPECIALIST_METHODS  // define this for testing

typedef enum { dtMillisecond, dtSecond, dtMinute, dtHour, dtDay } dtUnits_t;

typedef struct  {
	uint8_t alarmType              :4 ;  // enumeration of daily/weekly (in future: biweekly/semimonthly/monthly/annual)
	                                     // note that the current API only supports daily or weekly alarm periods
    uint8_t isEnabled              :1 ;  // the timer is only actioned if isEnabled is true 
    uint8_t isOneShot              :1 ;  // the timer will be de-allocated after trigger is processed 
										 }
    AlarmMode_t   ;
	
// new time based alarms should be added just before dtLastAlarmType
typedef enum  {dtNotAllocated, dtTimer, dtExplicitAlarm, dtDailyAlarm, dtWeeklyAlarm, dtLastAlarmType } dtAlarmPeriod_t ; // in future: dtBiweekly, dtMonthly, dtAnnual

// macro to return true if the given type is a time based alarm, false if timer or not allocated
#define dtIsAlarm(_type_)  (_type_ >= dtExplicitAlarm && _type_ < dtLastAlarmType) 

typedef uint8_t AlarmID_t;
typedef AlarmID_t AlarmId;  // Arduino friendly name

#define dtINVALID_ALARM_ID 255
#define dtINVALID_TIME     0L

class AlarmClass;  // forward reference
typedef void (*OnTick_t)(void *);  // alarm callback function typedef 

// class defining an alarm instance, only used by dtAlarmsClass
class AlarmClass
{  
private:

public:
  AlarmClass(); 
  OnTick_t onTickHandler; 
  void * pStorage;
  void updateNextTrigger();
  time_t value;
  time_t nextTrigger;
  AlarmMode_t Mode;
};

// class containing the collection of alarms
class TimeAlarmsClass
{
private:
   AlarmClass Alarm[dtNBR_ALARMS];
   void serviceAlarms();
   uint8_t isServicing;
   uint8_t servicedAlarmId; // the alarm currently being serviced
   AlarmID_t create( time_t value, OnTick_t onTickHandler, void * pStorage, uint8_t isOneShot, dtAlarmPeriod_t alarmType, uint8_t isEnabled=true);
   
public:
  TimeAlarmsClass();
  // functions to create alarms and timers

  AlarmID_t triggerOnce(time_t value, OnTick_t onTickHandler, void * pStorage);   // trigger once at the given time_t

  AlarmID_t alarmRepeat(time_t value, OnTick_t onTickHandler, void * pStorage);                    // trigger daily at given time of day
  AlarmID_t alarmRepeat(const int H,  const int M,  const int S, OnTick_t onTickHandler, void * pStorage); // as above, with hms arguments
  AlarmID_t alarmRepeat(const timeDayOfWeek_t DOW, const int H,  const int M,  const int S, OnTick_t onTickHandler, void * pStorage); // as above, with day of week 
 
  AlarmID_t alarmOnce(time_t value, OnTick_t onTickHandler, void * pStorage);                     // trigger once at given time of day
  AlarmID_t alarmOnce( const int H,  const int M,  const int S, OnTick_t onTickHandler, void * pStorage);  // as above, with hms arguments
  AlarmID_t alarmOnce(const timeDayOfWeek_t DOW, const int H,  const int M,  const int S, OnTick_t onTickHandler, void * pStorage); // as above, with day of week 
  
  AlarmID_t timerOnce(time_t value, OnTick_t onTickHandler, void * pStorage);   // trigger once after the given number of seconds 
  AlarmID_t timerOnce(const int H,  const int M,  const int S, OnTick_t onTickHandler, void * pStorage);   // As above with HMS arguments
  
  AlarmID_t timerRepeat(time_t value, OnTick_t onTickHandler, void * pStorage); // trigger after the given number of seconds continuously
  AlarmID_t timerRepeat(const int H,  const int M,  const int S, OnTick_t onTickHandler, void * pStorage);   // As above with HMS arguments
  
  void delay(unsigned long ms);
   
  // utility methods
  uint8_t getDigitsNow( dtUnits_t Units);         // returns the current digit value for the given time unit
  void waitForDigits( uint8_t Digits, dtUnits_t Units);  
  void waitForRollover(dtUnits_t Units);
 
  // low level methods 
  void enable(AlarmID_t ID);                // enable the alarm to trigger
  void disable(AlarmID_t ID);               // prevent the alarm from triggering   
  AlarmID_t getTriggeredAlarmId();          // returns the currently triggered  alarm id
  void write(AlarmID_t ID, time_t value);   // write the value (and enable) the alarm with the given ID  
  time_t read(AlarmID_t ID);                // return the value for the given timer  
  dtAlarmPeriod_t readType(AlarmID_t ID);   // return the alarm type for the given alarm ID 
  
#ifndef USE_SPECIALIST_METHODS  
private:  // the following methods are for testing and are not documented as part of the standard library
#endif
  void free(AlarmID_t ID);                  // free the id to allow its reuse 
  uint8_t count();                          // returns the number of allocated timers
  time_t getNextTrigger();                  // returns the time of the next scheduled alarm
  bool isAllocated(AlarmID_t ID);           // returns true if this id is allocated  
  bool isAlarm(AlarmID_t ID);               // returns true if id is for a time based alarm, false if its a timer or not allocated
};

extern TimeAlarmsClass Alarm;  // make an instance for the user

/*==============================================================================
 * MACROS
 *============================================================================*/

/* public */
#define waitUntilThisSecond(_val_) waitForDigits( _val_, dtSecond)
#define waitUntilThisMinute(_val_) waitForDigits( _val_, dtMinute)
#define waitUntilThisHour(_val_)   waitForDigits( _val_, dtHour)
#define waitUntilThisDay(_val_)    waitForDigits( _val_, dtDay)
#define waitMinuteRollover() waitForRollover(dtSecond)
#define waitHourRollover()   waitForRollover(dtMinute)
#define waitDayRollover()    waitForRollover(dtHour)

#define AlarmHMS(_hr_, _min_, _sec_) (_hr_ * SECS_PER_HOUR + _min_ * SECS_PER_MIN + _sec_)


#endif /* TimeAlarms2_h */

TimeAlarms2.cpp

/*
  TimeAlarms2TimeAlarms2.cpp - Arduino Time alarms for use with Time library   
  Copyright (c) 208-2011 Michael Margolis. 
  
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
 */
 
 /*
  2 July 2011 - replaced alarm types implied from alarm value with enums to make trigger logic more robust
              - this fixes bug in repeating weekly alarms - thanks to Vincent Valdy and draythomp for testing
*/

extern "C" {
#include <string.h> // for memset
}

#if ARDUINO > 22
#include <Arduino.h> 
#else
#include <WProgram.h> 
#endif

#include "TimeAlarms2.h"
#include "Time.h"

#define IS_ONESHOT  true   // constants used in arguments to create method
#define IS_REPEAT   false 


//**************************************************************
//* Alarm Class Constructor

AlarmClass::AlarmClass()
{
  Mode.isEnabled = Mode.isOneShot = 0;
  Mode.alarmType = dtNotAllocated;
  value = nextTrigger = 0;
  onTickHandler = NULL;  // prevent a callback until this pointer is explicitly set 
  pStorage = NULL;
}

//**************************************************************
//* Private Methods

 
void AlarmClass::updateNextTrigger()
{  
  if( (value != 0) && Mode.isEnabled )
  {
    time_t time = now();
    if( dtIsAlarm(Mode.alarmType) && nextTrigger <= time )   // update alarm if next trigger is not yet in the future
    {      
      if(Mode.alarmType == dtExplicitAlarm ) // is the value a specific date and time in the future
      {
        nextTrigger = value;  // yes, trigger on this value   
      }
      else if(Mode.alarmType == dtDailyAlarm)  //if this is a daily alarm
      {
        if( value + previousMidnight(now()) <= time)
        {
          nextTrigger = value + nextMidnight(time); // if time has passed then set for tomorrow
        }
        else
        {
          nextTrigger = value + previousMidnight(time);  // set the date to today and add the time given in value   
        }
      }
      else if(Mode.alarmType == dtWeeklyAlarm)  // if this is a weekly alarm
      {
        if( (value + previousSunday(now())) <= time)
        {
          nextTrigger = value + nextSunday(time); // if day has passed then set for the next week.
        }
        else
        {
          nextTrigger = value + previousSunday(time);  // set the date to this week today and add the time given in value 
        } 
      }
      else  // its not a recognized alarm type - this should not happen 
      {
        Mode.isEnabled = 0;  // Disable the alarm
      }	  
    }
    if( Mode.alarmType == dtTimer)
    {
      // its a timer
      nextTrigger = time + value;  // add the value to previous time (this ensures delay always at least Value seconds)
    }
  }
  else
  {
    Mode.isEnabled = 0;  // Disable if the value is 0
  }
}

//**************************************************************
//* Time Alarms Public Methods

TimeAlarmsClass::TimeAlarmsClass()
{
  isServicing = false;
  for(uint8_t id = 0; id < dtNBR_ALARMS; id++)
     free(id);   // ensure  all Alarms are cleared and available for allocation  
}

// this method creates a trigger at the given absolute time_t
// it replaces the call to alarmOnce with values greater than a week   
AlarmID_t TimeAlarmsClass::triggerOnce(time_t value, OnTick_t onTickHandler, void * pStorage){   // trigger once at the given time_t
     if( value > 0)
        return create( value, onTickHandler, pStorage, IS_ONESHOT, dtExplicitAlarm );
     else
        return dtINVALID_ALARM_ID; // dont't allocate if the time is greater than one day 	  
}

// this method will now return an error if the value is greater than one day - use DOW methods for weekly alarms   
AlarmID_t TimeAlarmsClass::alarmOnce(time_t value, OnTick_t onTickHandler, void * pStorage){   // trigger once at the given time of day
     if( value <= SECS_PER_DAY)
        return create( value, onTickHandler, pStorage, IS_ONESHOT, dtDailyAlarm );
     else
        return dtINVALID_ALARM_ID; // dont't allocate if the time is greater than one day 	  
}

AlarmID_t TimeAlarmsClass::alarmOnce(const int H,  const int M,  const int S,OnTick_t onTickHandler, void * pStorage){   // as above with HMS arguments
   return create( AlarmHMS(H,M,S), onTickHandler, pStorage, IS_ONESHOT, dtDailyAlarm );
}

AlarmID_t TimeAlarmsClass::alarmOnce(const timeDayOfWeek_t DOW, const int H,  const int M,  const int S, OnTick_t onTickHandler, void * pStorage){  // as above, with day of week 
   return create( (DOW-1) * SECS_PER_DAY + AlarmHMS(H,M,S), onTickHandler, pStorage, IS_ONESHOT, dtWeeklyAlarm );   
}
   
// this method will now return an error if the value is greater than one day - use DOW methods for weekly alarms   
AlarmID_t TimeAlarmsClass::alarmRepeat(time_t value, OnTick_t onTickHandler, void * pStorage){ // trigger daily at the given time
    if( value <= SECS_PER_DAY)
       return create( value, onTickHandler, pStorage, IS_REPEAT, dtDailyAlarm );
    else
       return dtINVALID_ALARM_ID; // dont't allocate if the time is greater than one day 	  
    }
    
    AlarmID_t TimeAlarmsClass::alarmRepeat(const int H,  const int M,  const int S, OnTick_t onTickHandler, void * pStorage){ // as above with HMS arguments
         return create( AlarmHMS(H,M,S), onTickHandler, pStorage, IS_REPEAT, dtDailyAlarm );
    }
    
    AlarmID_t TimeAlarmsClass::alarmRepeat(const timeDayOfWeek_t DOW, const int H,  const int M,  const int S, OnTick_t onTickHandler, void * pStorage){  // as above, with day of week 
       return create( (DOW-1) * SECS_PER_DAY + AlarmHMS(H,M,S), onTickHandler, pStorage, IS_REPEAT, dtWeeklyAlarm );      
    }
      
    AlarmID_t TimeAlarmsClass::timerOnce(time_t value, OnTick_t onTickHandler, void * pStorage){   // trigger once after the given number of seconds 
         return create( value, onTickHandler, pStorage, IS_ONESHOT, dtTimer );
    }
    
    AlarmID_t TimeAlarmsClass::timerOnce(const int H,  const int M,  const int S, OnTick_t onTickHandler, void * pStorage){   // As above with HMS arguments
      return create( AlarmHMS(H,M,S), onTickHandler, pStorage, IS_ONESHOT, dtTimer );
    }
      
    AlarmID_t TimeAlarmsClass::timerRepeat(time_t value, OnTick_t onTickHandler, void * pStorage){ // trigger after the given number of seconds continuously
         return create( value, onTickHandler, pStorage, IS_REPEAT, dtTimer);
    }
    
    AlarmID_t TimeAlarmsClass::timerRepeat(const int H,  const int M,  const int S, OnTick_t onTickHandler, void * pStorage){ // trigger after the given number of seconds continuously
         return create( AlarmHMS(H,M,S), onTickHandler, pStorage, IS_REPEAT, dtTimer);
    }
    
    void TimeAlarmsClass::enable(AlarmID_t ID)
    {
      if(isAllocated(ID)) {
        Alarm[ID].Mode.isEnabled = (Alarm[ID].value != 0) && (Alarm[ID].onTickHandler != 0) ;  // only enable if value is non zero and a tick handler has been set
        Alarm[ID].updateNextTrigger(); // trigger is updated whenever  this is called, even if already enabled	 
      }
    }
    
    void TimeAlarmsClass::disable(AlarmID_t ID)
    {
      if(isAllocated(ID))
        Alarm[ID].Mode.isEnabled = false;
    }
      
    // write the given value to the given alarm
    void TimeAlarmsClass::write(AlarmID_t ID, time_t value)
    {
      if(isAllocated(ID))
      {
        Alarm[ID].value = value;
        enable(ID);  // update trigger time
      }
    }
    
    // return the value for the given alarm ID
    time_t TimeAlarmsClass::read(AlarmID_t ID)
    {
      if(isAllocated(ID))
        return Alarm[ID].value ;
      else 	
        return dtINVALID_TIME;  
    }
    
    // return the alarm type for the given alarm ID
    dtAlarmPeriod_t TimeAlarmsClass::readType(AlarmID_t ID)
    {
      if(isAllocated(ID))
        return (dtAlarmPeriod_t)Alarm[ID].Mode.alarmType ;
      else 	
        return dtNotAllocated;  
    }

    void TimeAlarmsClass::free(AlarmID_t ID)
    {
      if(isAllocated(ID))
      {
        Alarm[ID].Mode.isEnabled = false;
    	Alarm[ID].Mode.alarmType = dtNotAllocated;
        Alarm[ID].onTickHandler = 0;
        Alarm[ID].pStorage = 0;
    	Alarm[ID].value = 0;
    	Alarm[ID].nextTrigger = 0;   	
      }
    }
    
    // returns the number of allocated timers
    uint8_t TimeAlarmsClass::count()
    {
       uint8_t c = 0; 
       for(uint8_t id = 0; id < dtNBR_ALARMS; id++)
       {
          if(isAllocated(id))
            c++;
       }
       return c;
    }
    
    // returns true only if id is allocated and the type is a time based alarm, returns false if not allocated or if its a timer
     bool TimeAlarmsClass::isAlarm(AlarmID_t ID)
     {
        return( isAllocated(ID) && dtIsAlarm(Alarm[ID].Mode.alarmType) );
     }
     
     // returns true if this id is allocated
     bool TimeAlarmsClass::isAllocated(AlarmID_t ID)
     {
        return( ID < dtNBR_ALARMS && Alarm[ID].Mode.alarmType != dtNotAllocated );
     }
     
    
    AlarmID_t TimeAlarmsClass::getTriggeredAlarmId()  //returns the currently triggered  alarm id
    // returns  dtINVALID_ALARM_ID if not invoked from within an alarm handler
    {
      if(isServicing)
           return  servicedAlarmId;  // new private data member used instead of local loop variable i in serviceAlarms();
      else
         return dtINVALID_ALARM_ID; // valid ids only available when servicing a callback
    }
     
    // following functions are not Alarm ID specific.
    void TimeAlarmsClass::delay(unsigned long ms)
    {
      unsigned long start = millis();
      while( millis() - start  <= ms)
        serviceAlarms();
    }
    		
    void TimeAlarmsClass::waitForDigits( uint8_t Digits, dtUnits_t Units)
    {
      while(Digits != getDigitsNow(Units) )
      {
        serviceAlarms();
      }
    }
    
    void TimeAlarmsClass::waitForRollover( dtUnits_t Units)
    {
      while(getDigitsNow(Units) == 0  ) // if its just rolled over than wait for another rollover	                            
        serviceAlarms();
      waitForDigits(0, Units);
    }
    
    uint8_t TimeAlarmsClass::getDigitsNow( dtUnits_t Units)
    {
      time_t time = now();
      if(Units == dtSecond) return numberOfSeconds(time);
      if(Units == dtMinute) return numberOfMinutes(time); 
      if(Units == dtHour) return numberOfHours(time);
      if(Units == dtDay) return dayOfWeek(time);
      return 255;  // This should never happen 
    }
    
    //***********************************************************
    //* Private Methods
    
    void TimeAlarmsClass::serviceAlarms()
    {
      if(! isServicing)
      {
        isServicing = true;
        for( servicedAlarmId = 0; servicedAlarmId < dtNBR_ALARMS; servicedAlarmId++)
        {
          if( Alarm[servicedAlarmId].Mode.isEnabled && (now() >= Alarm[servicedAlarmId].nextTrigger)  )
          {
            OnTick_t TickHandler = Alarm[servicedAlarmId].onTickHandler;
            void * pStorage = Alarm[servicedAlarmId].pStorage;
            
            if(Alarm[servicedAlarmId].Mode.isOneShot)
               free(servicedAlarmId);  // free the ID if mode is OnShot		
            else   
               Alarm[servicedAlarmId].updateNextTrigger();
            if( TickHandler != NULL) {        
              (*TickHandler)(pStorage);     // call the handler  
            }
          }
        }
        isServicing = false;
      }
    }
    
    // returns the absolute time of the next scheduled alarm, or 0 if none
     time_t TimeAlarmsClass::getNextTrigger()
     {
     time_t nextTrigger = 0xffffffff;  // the max time value
     
        for(uint8_t id = 0; id < dtNBR_ALARMS; id++)
        {
          if(isAllocated(id) )
          {
        	if(Alarm[id].nextTrigger <  nextTrigger)
    		   nextTrigger = Alarm[id].nextTrigger;	
          }      
    	}
        return nextTrigger == 0xffffffff ? 0 : nextTrigger;  	
     }
    
    // attempt to create an alarm and return true if successful
    AlarmID_t TimeAlarmsClass::create( time_t value, OnTick_t onTickHandler, void * pStorage, uint8_t isOneShot, dtAlarmPeriod_t alarmType, uint8_t isEnabled) 
    {
      if( ! (dtIsAlarm(alarmType) && now() < SECS_PER_YEAR)) // only create alarm ids if the time is at least Jan 1 1971
      {  
    	for(uint8_t id = 0; id < dtNBR_ALARMS; id++)
        {
          if( Alarm[id].Mode.alarmType == dtNotAllocated )
    	  {
    	  // here if there is an Alarm id that is not allocated
      	    Alarm[id].onTickHandler = onTickHandler;
      	    Alarm[id].pStorage = pStorage;
    	    Alarm[id].Mode.isOneShot = isOneShot;
    	    Alarm[id].Mode.alarmType = alarmType;
    	    Alarm[id].value = value;
    	    isEnabled ?  enable(id) : disable(id);   
            return id;  // alarm created ok
    	  }  
        }
      }
      return dtINVALID_ALARM_ID; // no IDs available or time is invalid
    }
    
    // make one instance for the user to use
    TimeAlarmsClass Alarm = TimeAlarmsClass() ;
    

[c language] callback function with parameter

    #include <stdio.h>

	  typedef struct StoreStruct {
	  	short duration, pin;
	  } Storage;

     typedef void (*Callback_t) (void *);
     Callback_t callbackHandler;
     
	Storage storage, *pStorage;
	
	  
    void caller2(Callback_t callbackHandler, void *pStorage)
    {      
    	printf ("Inside callback funtion\n");
    	callbackHandler( pStorage);
    }
	
	void callback_proc2(void * pStorage){
		printf("pin: %d, duration: %d\n", ((Storage *)pStorage)->pin, ((Storage *)pStorage)->duration);
	}

int main(int argc, char** argv)
{
	storage.pin = 13;
	storage.duration = 10;
	pStorage = &storage;
	caller2(callback_proc2, &storage);
	caller2(callback_proc2, pStorage);

    return 0;
}

[Arduino] Scheduler: NULL, millis was not declared in this scope

Arduino Scheduler compile Errors:

  • error: ‘NULL’ was not declared in this scope
  • error: ‘millis’ was not declared in this scope
arduino-nightly/libraries/Scheduler/Scheduler.cpp: In constructor ‘Scheduler::Scheduler()’:
arduino-nightly/libraries/Scheduler/Scheduler.cpp:33: error: ‘NULL’ was not declared in this scope
arduino-nightly/libraries/Scheduler/Scheduler.cpp: In member function ‘void Scheduler::update()’:
arduino-nightly/libraries/Scheduler/Scheduler.cpp:44: error: ‘millis’ was not declared in this scope
arduino-nightly/libraries/Scheduler/Scheduler.cpp: In member function ‘void Scheduler::schedule(void (*)(), unsigned int)’:
arduino-nightly/libraries/Scheduler/Scheduler.cpp:68: error: ‘millis’ was not declared in this scope

Solution:

Scheduler.h :
Replace <WProgram.h> with <Arduino.h> at the Scheduler.h file

//#include <WProgram.h>;
#include <Arduino.h>

[Javascript] parentNode.insertBefore(newnode, existingchild)

ref. http://reference.sitepoint.com/javascript/Node/insertBefore

This method is fantastically useful, but it can be tricky to remember the syntax. I remember it as a little sentence, like this: “into parent, insert new before old”.

If you don’t have a parent reference, it’s easy to extrapolate one from the node you do have:

 old.parentNode.insertBefore(new, old);

Conversely, if you only have a parent reference you can still insert at the beginning (providing that the parent has at least one child node already):

 parent.insertBefore(new, parent.firstChild);

Or the end (which is exactly equivalent to appendChild):

 parent.insertBefore(new, null);