From da6d8aff0c9e320bae9c33fd720ee7d7f6d3ab31 Mon Sep 17 00:00:00 2001 From: Elena ``of Valhalla'' Grandi Date: Sun, 4 Sep 2011 00:09:56 +0200 Subject: Use arscons for arduino sketch building http://code.google.com/p/arscons/ --- arduino_sketch/fuzzy_alarm_clock_ds1307/SConstruct | 290 ++++++++++++++++++ .../fuzzy_alarm_clock_ds1307.pde | 330 +++++++++++++++++++++ 2 files changed, 620 insertions(+) create mode 100644 arduino_sketch/fuzzy_alarm_clock_ds1307/SConstruct create mode 100644 arduino_sketch/fuzzy_alarm_clock_ds1307/fuzzy_alarm_clock_ds1307.pde (limited to 'arduino_sketch/fuzzy_alarm_clock_ds1307') diff --git a/arduino_sketch/fuzzy_alarm_clock_ds1307/SConstruct b/arduino_sketch/fuzzy_alarm_clock_ds1307/SConstruct new file mode 100644 index 0000000..acc5726 --- /dev/null +++ b/arduino_sketch/fuzzy_alarm_clock_ds1307/SConstruct @@ -0,0 +1,290 @@ +#!/usr/bin/python + +# scons script for the Arduino sketch +# http://code.google.com/p/arscons/ +# +# Copyright (C) 2010 by Homin Lee +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# You'll need the serial module: http://pypi.python.org/pypi/pyserial + +# Basic Usage: +# 1. make a folder which have same name of the sketch (ex. Blink/ for Blik.pde) +# 2. put the sketch and SConstruct(this file) under the folder. +# 3. to make the HEX. do following in the folder. +# $ scons +# 4. to upload the binary, do following in the folder. +# $ scons upload + +# Thanks to: +# * Ovidiu Predescu and Lee Pike +# for Mac port and bugfix. +# +# This script tries to determine the port to which you have an Arduino +# attached. If multiple USB serial devices are attached to your +# computer, you'll need to explicitly specify the port to use, like +# this: +# +# $ scons ARDUINO_PORT=/dev/ttyUSB0 +# +# To add your own directory containing user libraries, pass EXTRA_LIB +# to scons, like this: +# +# $ scons EXTRA_LIB= +# +from glob import glob +import sys +import re +import os +pathJoin = os.path.join + +env = Environment() +platform = env['PLATFORM'] + +def getUsbTty(rx): + usb_ttys = glob(rx) + if len(usb_ttys) == 1: return usb_ttys[0] + else: return None + +AVR_BIN_PREFIX = None +AVRDUDE_CONF = None + +if platform == 'darwin': + # For MacOS X, pick up the AVR tools from within Arduino.app + ARDUINO_HOME_DEFAULT = '/Applications/Arduino.app/Contents/Resources/Java' + ARDUINO_PORT_DEFAULT = getUsbTty('/dev/tty.usbserial*') +elif platform == 'win32': + # For Windows, use environment variables. + ARDUINO_HOME_DEFAULT = os.environ.get('ARDUINO_HOME') + ARDUINO_PORT_DEFAULT = os.environ.get('ARDUINO_PORT') +else: + # For Ubuntu Linux (9.10 or higher) + ARDUINO_HOME_DEFAULT = os.environ.get('ARDUINO_HOME','/usr/share/arduino/') #'/home/YOU/apps/arduino-00XX/' + ARDUINO_PORT_DEFAULT = getUsbTty('/dev/ttyUSB*') + AVR_BIN_PREFIX = 'avr-' + +ARDUINO_BOARD_DEFAULT = os.environ.get('ARDUINO_BOARD', 'atmega328') + +ARDUINO_HOME = ARGUMENTS.get('ARDUINO_HOME', ARDUINO_HOME_DEFAULT) +ARDUINO_PORT = ARGUMENTS.get('ARDUINO_PORT', ARDUINO_PORT_DEFAULT) +ARDUINO_BOARD = ARGUMENTS.get('ARDUINO_BOARD', ARDUINO_BOARD_DEFAULT) +ARDUINO_VER = ARGUMENTS.get('ARDUINO_VER', 22) # Arduino 0022 +RST_TRIGGER = ARGUMENTS.get('RST_TRIGGER', None) # use built-in pulseDTR() by default +EXTRA_LIB = ARGUMENTS.get('EXTRA_LIB', '/home/valhalla/sketchbook/libraries') # handy for adding another arduino-lib dir + +if not ARDUINO_HOME: + print 'ARDUINO_HOME must be defined.' + raise KeyError('ARDUINO_HOME') + +ARDUINO_CORE = pathJoin(ARDUINO_HOME, 'hardware/arduino/cores/arduino') +ARDUINO_SKEL = pathJoin(ARDUINO_CORE, 'main.cpp') +ARDUINO_CONF = pathJoin(ARDUINO_HOME, 'hardware/arduino/boards.txt') + +# Some OSs need bundle with IDE tool-chain +if platform == 'darwin' or platform == 'win32': + AVR_BIN_PREFIX = pathJoin(ARDUINO_HOME, 'hardware/tools/avr/bin', 'avr-') + AVRDUDE_CONF = pathJoin(ARDUINO_HOME, 'hardware/tools/avr/etc/avrdude.conf') + +ARDUINO_LIBS = [] +if EXTRA_LIB != None: + ARDUINO_LIBS += [EXTRA_LIB] +ARDUINO_LIBS += [pathJoin(ARDUINO_HOME, 'libraries')] + +# check given board name, ARDUINO_BOARD is valid one +ptnBoard = re.compile(r'^(.*)\.name=(.*)') +boards = {} +for line in open(ARDUINO_CONF): + result = ptnBoard.findall(line) + if result: + boards[result[0][0]] = result[0][1] +if not ARDUINO_BOARD in boards.keys(): + print ("ERROR! the given board name, %s is not in the supported board list:"%ARDUINO_BOARD) + print ("all available board names are:") + for name in boards.keys(): + print ("\t%s for %s"%(name.ljust(14), boards[name])) + print ("however, you may edit %s to add a new board."%ARDUINO_CONF) + sys.exit(-1) + +def getBoardConf(strPtn): + ptn = re.compile(strPtn) + for line in open(ARDUINO_CONF): + result = ptn.findall(line) + if result: + return result[0] + assert(False) + +MCU = getBoardConf(r'^%s\.build\.mcu=(.*)'%ARDUINO_BOARD) +MCU = ARGUMENTS.get('MCU', MCU) +F_CPU = getBoardConf(r'^%s\.build\.f_cpu=(.*)'%ARDUINO_BOARD) +F_CPU = ARGUMENTS.get('F_CPU', F_CPU) + +# There should be a file with the same name as the folder and with the extension .pde +TARGET = os.path.basename(os.path.realpath(os.curdir)) +assert(os.path.exists(TARGET+'.pde')) + +cFlags = ['-ffunction-sections', '-fdata-sections', '-fno-exceptions', + '-funsigned-char', '-funsigned-bitfields', '-fpack-struct', '-fshort-enums', + '-Os', '-mmcu=%s'%MCU] +envArduino = Environment(CC = AVR_BIN_PREFIX+'gcc', CXX = AVR_BIN_PREFIX+'g++', + CPPPATH = ['build/core'], CPPDEFINES = {'F_CPU':F_CPU, 'ARDUINO':ARDUINO_VER}, + CFLAGS = cFlags+['-std=gnu99'], CCFLAGS = cFlags, TOOLS = ['gcc','g++']) + +def fnProcessing(target, source, env): + wp = open ('%s'%target[0], 'wb') + wp.write(open(ARDUINO_SKEL).read()) + + types='''void + int char word long + float double byte long + boolean + uint8_t uint16_t uint32_t + int8_t int16_t int32_t + ''' + types=' | '.join(types.split()) + re_signature=re.compile(r"""^\s* ( + (?: (%s) \s+ )? + \w+ \s* + \( \s* ((%s) \s+ \*? \w+ (?:\s*,\s*)? )* \) + ) \s* {? \s* $""" % (types,types), re.MULTILINE|re.VERBOSE) + + prototypes = {} + + for file in glob(os.path.realpath(os.curdir) + "/*.pde"): + for line in open(file): + result = re_signature.findall(line) + if result: + prototypes[result[0][0]] = result[0][1] + + for name in prototypes.keys(): + print ("%s;"%(name)) + wp.write("%s;\n"%name) + + for file in glob(os.path.realpath(os.curdir) + "/*.pde"): + print file, TARGET + if not os.path.samefile(file, TARGET+".pde"): + wp.write('#line 1 "%s"\r\n' % file) + wp.write(open(file).read()) + + # Add this preprocessor directive to localize the errors. + sourcePath = str(source[0]).replace('\\', '\\\\'); + wp.write('#line 1 "%s"\r\n' % sourcePath) + wp.write(open('%s'%source[0]).read()) + +envArduino.Append(BUILDERS = {'Processing':Builder(action = fnProcessing, + suffix = '.cpp', src_suffix = '.pde')}) +envArduino.Append(BUILDERS={'Elf':Builder(action=AVR_BIN_PREFIX+'gcc '+ + '-mmcu=%s -Os -Wl,--gc-sections -o $TARGET $SOURCES -lm'%MCU)}) +envArduino.Append(BUILDERS={'Hex':Builder(action=AVR_BIN_PREFIX+'objcopy '+ + '-O ihex -R .eeprom $SOURCES $TARGET')}) + +# add arduino core sources +VariantDir('build/core', ARDUINO_CORE) +gatherSources = lambda x: glob(pathJoin(x, '*.c'))+\ + glob(pathJoin(x, '*.cpp'))+\ + glob(pathJoin(x, '*.S')) +core_sources = gatherSources(ARDUINO_CORE) +core_sources = filter(lambda x: not (os.path.basename(x) == 'main.cpp'), core_sources) +core_sources = map(lambda x: x.replace(ARDUINO_CORE, 'build/core/'), core_sources) + +# add libraries +libCandidates = [] +ptnLib = re.compile(r'^[ ]*#[ ]*include [<"](.*)\.h[>"]') +for line in open (TARGET+'.pde'): + result = ptnLib.findall(line) + if result: + # Look for the library directory that contains the header. + filename=result[0]+'.h' + for libdir in ARDUINO_LIBS: + for root, dirs, files in os.walk(libdir): + for f in files: + if f == filename: + libCandidates += [os.path.basename(root)] + +# Hack. In version 20 of the Arduino IDE, the Ethernet library depends +# implicitly on the SPI library. +if ARDUINO_VER >= 20 and 'Ethernet' in libCandidates: + libCandidates += ['SPI'] + +all_libs_sources = [] +index = 0 +for orig_lib_dir in ARDUINO_LIBS: + lib_sources = [] + lib_dir = 'build/lib_%02d'%index + VariantDir(lib_dir, orig_lib_dir) + for libPath in filter(os.path.isdir, glob(pathJoin(orig_lib_dir, '*'))): + libName = os.path.basename(libPath) + if not libName in libCandidates: + continue + envArduino.Append(CPPPATH = libPath.replace(orig_lib_dir, lib_dir)) + lib_sources = gatherSources(libPath) + utilDir = pathJoin(libPath, 'utility') + if os.path.exists(utilDir) and os.path.isdir(utilDir): + lib_sources += gatherSources(utilDir) + envArduino.Append(CPPPATH = utilDir.replace(orig_lib_dir, lib_dir)) + lib_sources = map(lambda x: x.replace(orig_lib_dir, lib_dir), lib_sources) + all_libs_sources += lib_sources + index += 1 + +# Convert sketch(.pde) to cpp +envArduino.Processing('build/'+TARGET+'.cpp', 'build/'+TARGET+'.pde') +VariantDir('build', '.') + +sources = ['build/'+TARGET+'.cpp'] +sources += all_libs_sources +sources += core_sources +# Add raw sources which live in sketch dir. +# sources += gatherSources('.') + +# Finally Build!! +objs = envArduino.Object(sources) #, LIBS=libs, LIBPATH='.') +envArduino.Elf(TARGET+'.elf', objs) +envArduino.Hex(TARGET+'.hex', TARGET+'.elf') + +# Print Size +# TODO: check binary size +MAX_SIZE = getBoardConf(r'^%s\.upload.maximum_size=(.*)'%ARDUINO_BOARD) +print ("maximum size for hex file: %s bytes"%MAX_SIZE) +envArduino.Command(None, TARGET+'.hex', AVR_BIN_PREFIX+'size --target=ihex $SOURCE') + +# Reset +def pulseDTR(target, source, env): + import serial + import time + ser = serial.Serial(ARDUINO_PORT) + ser.setDTR(1) + time.sleep(0.5) + ser.setDTR(0) + ser.close() + +if RST_TRIGGER: + reset_cmd = '%s %s'%(RST_TRIGGER, ARDUINO_PORT) +else: + reset_cmd = pulseDTR + +# Upload +UPLOAD_PROTOCOL = getBoardConf(r'^%s\.upload\.protocol=(.*)'%ARDUINO_BOARD) +UPLOAD_SPEED = getBoardConf(r'^%s\.upload\.speed=(.*)'%ARDUINO_BOARD) + +if UPLOAD_PROTOCOL == 'stk500': + UPLOAD_PROTOCOL = 'stk500v1' + + +avrdudeOpts = ['-V', '-F', '-c %s'%UPLOAD_PROTOCOL, '-b %s'%UPLOAD_SPEED, + '-p %s'%MCU, '-P %s'%ARDUINO_PORT, '-U flash:w:$SOURCES'] +if AVRDUDE_CONF: + avrdudeOpts += ['-C %s'%AVRDUDE_CONF] + +fuse_cmd = '%s %s'%(pathJoin(os.path.dirname(AVR_BIN_PREFIX), 'avrdude'), + ' '.join(avrdudeOpts)) + +upload = envArduino.Alias('upload', TARGET+'.hex', [reset_cmd, fuse_cmd]); +AlwaysBuild(upload) + +# Clean build directory +envArduino.Clean('all', 'build/') + +# vim: et sw=4 fenc=utf-8: diff --git a/arduino_sketch/fuzzy_alarm_clock_ds1307/fuzzy_alarm_clock_ds1307.pde b/arduino_sketch/fuzzy_alarm_clock_ds1307/fuzzy_alarm_clock_ds1307.pde new file mode 100644 index 0000000..8c24791 --- /dev/null +++ b/arduino_sketch/fuzzy_alarm_clock_ds1307/fuzzy_alarm_clock_ds1307.pde @@ -0,0 +1,330 @@ +#include + +#include + +// minutes of "dawn" before alarm +#define TIN 30 +// "dawn" + "daylight" +#define TDAY 45 +// "dawn" + "daylight" + blue blinding light +#define TOUT 75 + +// number of available alarms; max 10 for storage in the DS1307 ram +#define NALARMS 4 + +// pins and addressed +#define RPIN 3 +#define YPIN 5 +#define BPIN 6 + +int st = 0; // alarm status (minutes from alarm - TIN) +char alarms[NALARMS][5]; // alarm settings +char cmin; // current minute +int a = -1; // current alarm +char dbg = 0; // print debug informations + +void setup () { + Serial.begin(9600); + Wire.begin(); + + pinMode(RPIN,OUTPUT); + pinMode(YPIN,OUTPUT); + pinMode(BPIN,OUTPUT); + + digitalWrite(RPIN,255); + digitalWrite(YPIN,255); + digitalWrite(BPIN,0); + + // if the RTC is already running read alarms and status, + // otherwise set everything to a sane default + if ( RTC.readData(0x00) >> 7 ) { + for ( int i = 0 ; i < NALARMS ; i ++ ) { + for ( int j = 0; j < 5 ; j ++ ) { + alarms[i][j] = 0; + } + } + st = 0; + a = -1; + save_status(); + } else { + st = RTC.readData(0x08); + a = RTC.readData(0x09); + cmin = RTC.readData(0x0a); + // This only works if the arduino had no power for a + // "short" time. This is by design. :D + RTC.readClock(); + st = st + (RTC.getMinutes() - cmin) % 60; + cmin = RTC.getMinutes(); + save_status(); + for ( int i = 0; i < NALARMS ; i ++ ) { + for ( int j = 0; j < 5 ; j ++ ) { + alarms[i][j] = RTC.readData(0x0b + i*5 + j); + } + } + } + +} + +void loop () { + + // read commands from serial + check_serial(); + + // read time, check alarms + check_time(); + + if ( dbg ) { + s_print_time(); + Serial.print("st: "); + Serial.print(st,DEC); + Serial.print(", a: "); + Serial.print(a,DEC); + Serial.print(", cmin: "); + Serial.println(cmin,DEC); + } + + // act on status: LEDs and buzzer + if ( st > 0 ) { + set_leds(); + } + + // wait about till the next second + + delay(1000); + +} + +void save_status() { + RTC.writeData(0x08,st); + RTC.writeData(0x09,a); + RTC.writeData(0x0a,cmin); +} + +// ****** Serial interface management *************************************** // + +void check_serial() { + int rec = Serial.read(); + switch (rec) { + case 'a': + s_set_alarm(); + break; + case 's': + s_set_time(); + break; + case 'p': + s_print_alarms(); + break; + case 't': + s_print_time(); + break; + case 'd': + s_toggle_debug(); + break; + case 'h': + s_print_help(); + break; + } +} + +void s_set_alarm() { + int i = s_read_dig(); + for ( int j = 0; j < 5 ; j++) { + alarms[i][j] = s_read_2hex(); + } + for ( int j = 0; j < 5 ; j++ ) { + RTC.writeData(0x0b + i*5 + j,alarms[i][j]); + } + Serial.print("Alarm "); + Serial.print(i,DEC); + Serial.println(" set."); +} + +void s_set_time() { + RTC.start(); + RTC.setYear(s_read_2dig()); + RTC.setMonth(s_read_2dig()); + RTC.setDate(s_read_2dig()); + RTC.setDayOfWeek(s_read_dig()); + RTC.setHours(s_read_2dig()); + RTC.setMinutes(s_read_2dig()); + RTC.setSeconds(s_read_2dig()); + RTC.setClock(); + Serial.print("Time set: "); + s_print_time(); +} + +int s_read_dig() { + int rec; + rec = Serial.read(); + while ( rec == -1 ) { + rec = Serial.read(); + } + return rec - 48; +} + +int s_read_2dig() { + int n; + n = s_read_dig() * 10; + n = n + s_read_dig(); + return n; +} + +int s_read_hex() { + int rec; + rec = Serial.read(); + while ( rec == -1 ) { + rec = Serial.read(); + } + if ( rec >= 48 && rec < 58 ) { + return rec - 48; + } else if ( rec >= 65 && rec < 71 ) { + return rec - 55; + } else if ( rec >= 97 && rec < 102 ) { + return rec - 87; + } else { + return 0; + } +} + +int s_read_2hex() { + int n; + n = s_read_hex() * 16; + n = n + s_read_hex(); + return n; +} + +void s_print_alarms() { + for ( int i = 0; i < NALARMS ; i++) { + Serial.print(i,DEC); + Serial.print(" - "); + for ( int j = 0; j < 5 ; j++) { + Serial.print(alarms[i][j],DEC); + Serial.print(" "); + } + Serial.println(""); + } +} + +void s_print_time() { + RTC.readClock(); + Serial.print(RTC.getYear(),DEC); + Serial.print("/"); + Serial.print(RTC.getMonth(),DEC); + Serial.print("/"); + Serial.print(RTC.getDate(),DEC); + Serial.print(" ("); + Serial.print(RTC.getDayOfWeek(),DEC); + Serial.print(") "); + Serial.print(RTC.getHours(),DEC); + Serial.print(":"); + Serial.print(RTC.getMinutes(),DEC); + Serial.print(":"); + Serial.println(RTC.getSeconds(),DEC); +} + +void s_toggle_debug() { + if ( dbg ) { + dbg = 0; + } else { + dbg = 1; + } +} + +void s_print_help() { + Serial.println(""); + Serial.println(" a - set an alarm"); + Serial.println(" is nhhhhhhhhhh"); + Serial.println(" where hh are hex values"); + Serial.println(" s - set the clock"); + Serial.println(" is yymmgguHHMMSS"); + Serial.println(" p - print the alarms"); + Serial.println(" t - print the clock"); + Serial.println(" d - toggle printing of debug informations"); + Serial.println(" h - print this help"); +} + +// ****** Time management *************************************************** // + +// Set the current time +void set_time(int y,int m,int d, int w, int hh, int mm, int ss) { + RTC.setYear(y); + RTC.setMonth(m); + RTC.setDate(m); + RTC.setDayOfWeek(w); + RTC.setHours(hh); + RTC.setMinutes(mm); + RTC.setSeconds(ss); + RTC.switchTo24h(); + RTC.setClock(); +} + +void check_time() { + RTC.readClock(); + + int mm = RTC.getMinutes(); + int hour = RTC.getHours(); + int wday = RTC.getDayOfWeek(); + int day = RTC.getDate(); + int month = RTC.getMonth(); + + if ( a < 0 ) { + for ( int i = 0; i < NALARMS ; i ++ ) { + // check alarm i + if ( ( alarms[i][0] & ( 1 << (wday - 1) ) ) || + (month == alarms[i][1] && day == alarms[i][2]) ) { + // this is alarm day! + if ( hour == alarms[i][3] && mm == alarms[i][4]) { + // this is alarm hour! + a = i; + st = 1; + cmin = mm; + save_status(); + if ( ( alarms[i][0] & 128 ) == 0 ) { + // this alarm won't be repeated + alarms[i] = { 0,0,0,0,0 }; + for ( int j = 0; j < 5 ; j++ ) { + RTC.writeData(0x0b + i*5 + j,0); + } + } + break; + } + } + } + } else { + if ( cmin != mm ) { + cmin = mm; + st++; + save_status(); + } + } + +} + +// ****** LED management **************************************************** // + +void set_leds() { + if ( st > 0 && st <= TIN) { + int y = int(float(st*255)/TIN); + int r = 255 - y; + analogWrite(RPIN,r); + analogWrite(YPIN,y); + } else if ( st > TIN && st < TDAY ) { + analogWrite(RPIN,0); + analogWrite(YPIN,255); + analogWrite(BPIN,0); + } else if (st >= TDAY && st < TOUT) { + analogWrite(RPIN,0); + analogWrite(YPIN,0); + analogWrite(BPIN,255); + } else if (st == TOUT) { + // reset stuff + st = 0; + a = -1; + save_status(); + analogWrite(RPIN,255); + analogWrite(YPIN,0); + analogWrite(BPIN,0); + } +} + +// vim: set filetype=c: -- cgit v1.2.3