From ad99581285b9097fd90de288e73a97843a1091ee Mon Sep 17 00:00:00 2001 From: maniacbug Date: Fri, 3 Jun 2011 06:42:47 -0700 Subject: [PATCH] Added a new example --- examples/led_remote/.gitignore | 1 + examples/led_remote/led_remote.pde | 247 +++++++++++++++++++++++ examples/led_remote/makefile | 305 +++++++++++++++++++++++++++++ examples/led_remote/printf.h | 33 ++++ 4 files changed, 586 insertions(+) create mode 100644 examples/led_remote/.gitignore create mode 100644 examples/led_remote/led_remote.pde create mode 100644 examples/led_remote/makefile create mode 100644 examples/led_remote/printf.h diff --git a/examples/led_remote/.gitignore b/examples/led_remote/.gitignore new file mode 100644 index 0000000..ea1472e --- /dev/null +++ b/examples/led_remote/.gitignore @@ -0,0 +1 @@ +output/ diff --git a/examples/led_remote/led_remote.pde b/examples/led_remote/led_remote.pde new file mode 100644 index 0000000..e3cb84d --- /dev/null +++ b/examples/led_remote/led_remote.pde @@ -0,0 +1,247 @@ +/* + Copyright (C) 2011 James Coliz, Jr. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * Example LED Remote + * + * This is an example of how to use the RF24 class to control a remote + * bank of LED's using buttons on a remote control. + * + * On the 'remote', connect any number of buttons or switches from + * an arduino pin to ground. Update 'button_pins' to reflect the + * pins used. + * + * On the 'led' board, connect the same number of LED's from an + * arduino pin to a resistor to ground. Update 'led_pins' to reflect + * the pins used. Also connect a separate pin to ground and change + * the 'role_pin'. This tells the sketch it's running on the LED board. + * + * Every time the buttons change on the remote, the entire state of + * buttons is send to the led board, which displays the state. + */ + +#include +#include "nRF24L01.h" +#include "RF24.h" +#include "printf.h" + +// +// Hardware configuration +// + +// Set up nRF24L01 radio on SPI bus plus pins 8 & 9 + +RF24 radio(8,9); + +// sets the role of this unit in hardware. Connect to GND to be the 'led' board receiver +// Leave open to be the 'remote' transmitter +const int role_pin = A4; + +// Pins on the remote for buttons +const uint8_t button_pins[] = { 2,3,4,5,6,7 }; +const uint8_t num_button_pins = sizeof(button_pins); + +// Pins on the LED board for LED's +const uint8_t led_pins[] = { 2,3,4,5,6,7 }; +const uint8_t num_led_pins = sizeof(led_pins); + +// +// Topology +// + +// Single radio pipe address for the 2 nodes to communicate. +const uint64_t pipe = 0xE8E8F0F0E1LL; + +// +// Role management +// +// Set up role. This sketch uses the same software for all the nodes in this +// system. Doing so greatly simplifies testing. The hardware itself specifies +// which node it is. +// +// This is done through the role_pin +// + +// The various roles supported by this sketch +typedef enum { role_remote = 1, role_led } role_e; + +// The debug-friendly names of those roles +const char* role_friendly_name[] = { "invalid", "Remote", "LED Board"}; + +// The role of the current running sketch +role_e role; + +// +// Payload +// + +uint8_t button_states[num_button_pins]; + +// +// Setup +// + +void setup(void) +{ + // + // Role + // + + // set up the role pin + pinMode(role_pin, INPUT); + digitalWrite(role_pin,HIGH); + delay(20); // Just to get a solid reading on the role pin + + // read the address pin, establish our role + if ( digitalRead(role_pin) ) + role = role_remote; + else + role = role_led; + + // + // Print preamble + // + + Serial.begin(9600); + printf_begin(); + printf("\n\rRF24/examples/led_remote/\n\r"); + printf("ROLE: %s\n\r",role_friendly_name[role]); + + // + // Setup and configure rf radio + // + + radio.begin(); + + // + // Open pipes to other nodes for communication + // + + // This simple sketch opens a single pipes for these two nodes to communicate + // back and forth. One listens on it, the other talks to it. + + if ( role == role_remote ) + { + radio.openWritingPipe(pipe); + } + else + { + radio.openReadingPipe(1,pipe); + } + + // + // Start listening + // + + if ( role == role_led ) + radio.startListening(); + + // + // Dump the configuration of the rf unit for debugging + // + + radio.printDetails(); + + // + // Set up buttons / LED's + // + + // Set pull-up resistors for all buttons + if ( role == role_remote ) + { + int i = num_button_pins; + while(i--) + { + pinMode(button_pins[i],INPUT); + digitalWrite(button_pins[i],HIGH); + } + } + + // Turn LED's ON until we start getting keys + if ( role == role_led ) + { + int i = num_button_pins; + while(i--) + { + pinMode(button_pins[i],OUTPUT); + digitalWrite(button_pins[i],HIGH); + } + } + +} + +// +// Loop +// + +void loop(void) +{ + // + // Remote role. If the state of any button has changed, send the whole state of + // all buttons. + // + + if ( role == role_remote ) + { + // Get the current state of buttons, and + // Test if the current state is different from the last state we sent + int i = num_button_pins; + bool different = false; + while(i--) + { + uint8_t state = ! digitalRead(button_pins[i]); + if ( state != button_states[i] ) + { + different = true; + button_states[i] = state; + } + } + + // Send the state of the buttons to the LED board + if ( different ) + { + printf("Now sending..."); + bool ok = radio.write( button_states, num_button_pins ); + if (ok) + printf("ok\n\r"); + else + printf("failed\n\r"); + } + + // Try again in a short while + delay(20); + } + + // + // LED role. Receive the state of all buttons, and reflect that in the LEDs + // + + if ( role == role_led ) + { + // if there is data ready + if ( radio.available() ) + { + // Dump the payloads until we've gotten everything + boolean done = false; + while (!done) + { + // Fetch the payload, and see if this was the last one. + done = radio.read( button_states, num_button_pins ); + + // Spew it + printf("Got buttons\n\r"); + + // Set all the LED's according to the buttons + int i = num_led_pins; + while(i--) + digitalWrite(led_pins[i],button_states[i]); + } + } + } +} +// vim:ai:cin:sts=2 sw=2 ft=cpp diff --git a/examples/led_remote/makefile b/examples/led_remote/makefile new file mode 100644 index 0000000..493a159 --- /dev/null +++ b/examples/led_remote/makefile @@ -0,0 +1,305 @@ +# Arduino Makefile +# Arduino adaptation by mellis, eighthave, oli.keller +# Modified by Kerry Wong to support NetBeans +# Modified by Rob Gray (Graynomad) for use with Windows and no IDE +# This works in my environment and I use it to program two different +# 328-based boards and a Mega2560. It's not necessarily robust and +# I may have broken something in the original file that I don't use. +# +# This makefile allows you to build sketches from the command line +# without the Arduino environment. +# +# Instructions for using the makefile: +# +# 1. Copy this file into the folder with your sketch. The project code file +# should have a .c extension however the file gets copied to a .cpp before +# compilation so you still write in C++. +# +# 2. Modify the lines between the double ### rows to set the paths +# comm ports etc for your system. EG. c:/progra~1/arduino/arduino-00 +# for the Arduino IDE, Note the use of short folder name, don't use +# "Program files" because spaces will break the build. +# +# Set the line containing "MCU" to match your board's processor. +# Typically ATmega328 or ATmega2560. If you're using a LilyPad Arduino, +# change F_CPU to 8000000. +# +# 3. At the command line, change to the directory containing your +# program's file and the makefile. +# +# 4. Type "make" and press enter to compile/verify your program. +# The default make target will also perform the uplode using avrdude. +# +# The first time this is done all required libraries will be built +# and a core.a file will be created in the output folder. +# +# NOTES: +# All output goes into a folder called "output" underneath the working folder. +# The default all: target creates symbol (.sym) and expanded assembly +# (.lss) files and uploads the program. +# +# +########################################################## +########################################################## +# Select processor here +MCU = atmega328p +#MCU = atmega2560 + +ifeq ($(MCU),atmega2560) +UPLOAD_RATE = 115200 +AVRDUDE_PROTOCOL = stk500v2 +COM = 39 +endif + +ifeq ($(MCU),atmega328p) +UPLOAD_RATE = 57600 +AVRDUDE_PROTOCOL = stk500v1 +COM = 33 +endif + +UNAME := $(shell uname) + +ifeq ($(UNAME),Darwin) +ARDUINO_VERSION = 21 +ARDUINO_DIR = /opt/arduino-00$(ARDUINO_VERSION) +AVR_TOOLS_PATH = $(ARDUINO_DIR)/hardware/tools/avr/bin +AVRDUDECONFIG_PATH = $(ARDUINO_DIR)/hardware/tools/avr/etc +PORT = /dev/tty.usbserial-A600eHIs +PORT2 = /dev/tty.usbserial-A9007LmI +PORT3 = /dev/tty.usbserial-A40081RP +else +ARDUINO_VERSION = 22 +ARDUINO_DIR = /opt/arduino-00$(ARDUINO_VERSION) +AVR_TOOLS_PATH = /usr/bin +AVRDUDECONFIG_PATH = $(ARDUINO_DIR)/hardware/tools +PORT = /dev/ttyUSB0 +PORT2 = /dev/ttyUSB1 +endif + +# Temporary testing of github Arduino environment +OLD_DIR = /opt/arduino-00$(ARDUINO_VERSION) +AVR_TOOLS_PATH = $(OLD_DIR)/hardware/tools/avr/bin +AVRDUDECONFIG_PATH = $(OLD_DIR)/hardware/tools/avr/etc +ARDUINO_DIR = /opt/Arduino + +PROJECT_NAME = $(notdir $(PWD)) +PROJECT_DIR = . +ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino +ARDUINO_AVR = $(ARDUINO_DIR)/hardware/tools/avr/avr/include/avr +ARDUINO_LIB = $(ARDUINO_DIR)/libraries +F_CPU = 16000000 + +########################################################## +########################################################## + +# Note that if your program has dependencies other than those +# already listed below, you will need to add them accordingly. +C_MODULES = \ +$(ARDUINO_CORE)/wiring_pulse.c \ +$(ARDUINO_CORE)/wiring_analog.c \ +$(ARDUINO_CORE)/pins_arduino.c \ +$(ARDUINO_CORE)/wiring.c \ +$(ARDUINO_CORE)/wiring_digital.c \ +$(ARDUINO_CORE)/WInterrupts.c \ +$(ARDUINO_CORE)/wiring_shift.c \ + +CXX_MODULES = \ +$(ARDUINO_CORE)/Tone.cpp \ +$(ARDUINO_CORE)/main.cpp \ +$(ARDUINO_CORE)/WMath.cpp \ +$(ARDUINO_CORE)/Print.cpp \ +$(ARDUINO_CORE)/HardwareSerial.cpp \ +$(ARDUINO_LIB)/SPI/SPI.cpp \ +$(ARDUINO_LIB)/EEPROM/EEPROM.cpp \ +../../RF24.cpp + +CXX_APP = output/$(PROJECT_NAME).cpp +MODULES = $(C_MODULES) $(CXX_MODULES) +SRC = $(C_MODULES) +CXXSRC = $(CXX_MODULES) $(CXX_APP) +FORMAT = ihex + +# Name of this Makefile (used for "make depend"). +MAKEFILE = Makefile + +# Debugging format. +# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2. +# AVR (extended) COFF requires stabs, plus an avr-objcopy run. +#DEBUG = stabs +DEBUG = + +OPT = s + +# Place -D or -U options here +CDEFS = -DF_CPU=$(F_CPU)L -DARDUINO=$(ARDUINO_VERSION) +CXXDEFS = -DF_CPU=$(F_CPU)L -DARDUINO=$(ARDUINO_VERSION) + +# Place -I options here +CINCS = -I$(ARDUINO_LIB)/EEPROM -I$(ARDUINO_CORE) -I$(ARDUINO_LIB) -I$(PROJECT_DIR) -I$(ARDUINO_AVR) -I$(ARDUINO_LIB)/SPI -I$(MY_LIB)/Bounce -I$(MY_LIB)/ButtonSpace -I../.. + +CXXINCS = -I$(ARDUINO_CORE) -I$(ARDUINO_LIB) + +# Compiler flag to set the C Standard level. +# c89 - "ANSI" C +# gnu89 - c89 plus GCC extensions +# c99 - ISO C99 standard (not yet fully implemented) +# gnu99 - c99 plus GCC extensions +#CSTANDARD = -std=gnu99 +CDEBUG = -g$(DEBUG) +#CWARN = -Wall -Wstrict-prototypes +CWARN = -Wall # show all warnings +#CWARN = -w # suppress all warnings +CMAP = -Wl,-Map,output.map +####CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CTUNING = -ffunction-sections -fdata-sections +CXXTUNING = -fno-exceptions -ffunction-sections -fdata-sections +#CEXTRA = -Wa,-adhlns=$(<:.c=.lst) +MMCU = -mmcu=$(MCU) + +CFLAGS = $(CDEBUG) -O$(OPT) $(CMAP) $(CWARN) $(CTUNING) $(MMCU) $(CDEFS) $(CINCS) $(CSTANDARD) $(CEXTRA) +CXXFLAGS = $(CDEBUG) -O$(OPT) $(CWARN) $(CXXTUNING) $(CDEFS) $(CINCS) +#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs +LDFLAGS = -O$(OPT) -lm -Wl,--gc-sections +#LDFLAGS = -O$(OPT) -lm -Wl,-Map,output/$(PROJECT_NAME).map + +# Programming support using avrdude. Settings and variables. +AVRDUDE_PORT = $(PORT) +AVRDUDE_WRITE_FLASH = -U flash:w:output/$(PROJECT_NAME).hex:i + +AVRDUDE_FLAGS = -V -F -D -C $(AVRDUDECONFIG_PATH)/avrdude.conf \ +-p $(MCU) -c $(AVRDUDE_PROTOCOL) -b $(UPLOAD_RATE) + +# Program settings +CC = $(AVR_TOOLS_PATH)/avr-gcc +CXX = $(AVR_TOOLS_PATH)/avr-g++ +LD = $(AVR_TOOLS_PATH)/avr-gcc +OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy +OBJDUMP = $(AVR_TOOLS_PATH)/avr-objdump +AR = $(AVR_TOOLS_PATH)/avr-ar +SIZE = $(AVR_TOOLS_PATH)/avr-size +NM = $(AVR_TOOLS_PATH)/avr-nm +AVRDUDE = $(AVR_TOOLS_PATH)/avrdude +REMOVE = rm -f +MV = mv -f + +# Define all object files. +OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o) +OBJ_MODULES = $(C_MODULES:.c=.o) $(CXX_MODULES:.cpp=.o) + +# Define all listing files. +LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst) + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = $(CFLAGS) -mmcu=$(MCU) +ALL_CXXFLAGS = $(CXXFLAGS) -mmcu=$(MCU) +ALL_ASFLAGS = -x assembler-with-cpp $(ASFLAGS) -mmcu=$(MCU) +ALL_LDFLAGS = $(LDFLAGS) -mmcu=$(MCU) + +# Default target. +# This is th etarget that gets executed with a make command +# that has no parameters, ie "make". +all: applet_files build sym lss size upload + +build: elf hex + +output/$(PROJECT_NAME).cpp: $(PROJECT_NAME).pde + test -d output || mkdir output + echo "#include " > $@ + echo "#line 1 \"$<\"" >> $@ + cat $< >> $@ + +elf: output/$(PROJECT_NAME).elf +hex: output/$(PROJECT_NAME).hex +eep: output/$(PROJECT_NAME).eep +lss: output/$(PROJECT_NAME).lss +#sym: output/$(PROJECT_NAME).sym + +# Upload HEX file to Arduino +upload: upload1 upload2 + +upload1: output/$(PROJECT_NAME).hex + $(AVRDUDE) $(AVRDUDE_FLAGS) -P $(PORT) $(AVRDUDE_WRITE_FLASH) + +upload2: output/$(PROJECT_NAME).hex + $(AVRDUDE) $(AVRDUDE_FLAGS) -P $(PORT2) $(AVRDUDE_WRITE_FLASH) + +upload3: output/$(PROJECT_NAME).hex + $(AVRDUDE) $(AVRDUDE_FLAGS) -P $(PORT3) $(AVRDUDE_WRITE_FLASH) + +sym: + $(NM) -n -C --format=posix output/$(PROJECT_NAME).elf > output/$(PROJECT_NAME).sym + +# Display size of file. +size: + $(SIZE) output/$(PROJECT_NAME).elf + +# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB. +COFFCONVERT=$(OBJCOPY) --debugging \ +--change-section-address .data-0x800000 \ +--change-section-address .bss-0x800000 \ +--change-section-address .noinit-0x800000 \ +--change-section-address .eeprom-0x810000 + +coff: output/$(PROJECT_NAME).elf + $(COFFCONVERT) -O coff-avr output/$(PROJECT_NAME).elf $(PROJECT_NAME).cof + + extcoff: $(PROJECT_NAME).elf + $(COFFCONVERT) -O coff-ext-avr output/$(PROJECT_NAME).elf $(PROJECT_NAME).cof + +.SUFFIXES: .elf .hex .eep .lss .sym + +.elf.hex: + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +.elf.eep: + $(OBJCOPY) -O $(FORMAT) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --no-change-warnings \ + --change-section-lma .eeprom=0 $< $@ + +# Create extended listing file from ELF output file. +.elf.lss: + $(OBJDUMP) -h -S $< > $@ + +# Link: create ELF output file from library. +#output/$(PROJECT_NAME).elf: $(PROJECT_NAME).c output/core.a +output/$(PROJECT_NAME).elf: output/$(PROJECT_NAME).o output/core.a + $(LD) $(ALL_LDFLAGS) -o $@ output/$(PROJECT_NAME).o output/core.a + +output/core.a: $(OBJ_MODULES) + @for i in $(OBJ_MODULES); do echo $(AR) rcs output/core.a $$i; $(AR) rcs output/core.a $$i; done + +# Compile: create object files from C++ source files. +.cpp.o: + $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ + +# Compile: create object files from C source files. +.c.o: + $(CC) -c $(ALL_CFLAGS) $< -o $@ + +# Compile: create assembler files from C source files. +.c.s: + $(CC) -S $(ALL_CFLAGS) $< -o $@ + +# Assemble: create object files from assembler source files. +.S.o: + $(CC) -c $(ALL_ASFLAGS) $< -o $@ + +# Automatic dependencies +%.d: %.c + $(CC) -M $(ALL_CFLAGS) $< | sed "s;$(notdir $*).o:;$*.o $*.d:;" > $@ + +%.d: %.cpp + $(CXX) -M $(ALL_CXXFLAGS) $< | sed "s;$(notdir $*).o:;$*.o $*.d:;" > $@ + +# Target: clean project. +clean: + $(REMOVE) output/$(PROJECT_NAME).hex output/$(PROJECT_NAME).eep output/$(PROJECT_NAME).cof output/$(PROJECT_NAME).elf \ + output/$(PROJECT_NAME).map output/$(PROJECT_NAME).sym output/$(PROJECT_NAME).lss output/core.a \ + $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d) + +#.PHONY: all build elf hex eep lss sym program coff extcoff clean applet_files sizebefore sizeafter +.PHONY: all build elf hex eep lss sym program coff extcoff applet_files sizebefore sizeafter + +#include $(SRC:.c=.d) +#include $(CXXSRC:.cpp=.d) diff --git a/examples/led_remote/printf.h b/examples/led_remote/printf.h new file mode 100644 index 0000000..63501e4 --- /dev/null +++ b/examples/led_remote/printf.h @@ -0,0 +1,33 @@ +/* + Copyright (C) 2011 James Coliz, Jr. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + version 2 as published by the Free Software Foundation. + */ + +/** + * @file printf.h + * + * Setup necessary to direct stdout to the Arduino Serial library, which + * enables 'printf' + */ + +#ifndef __PRINTF_H__ +#define __PRINTF_H__ + +#include "WProgram.h" + +int serial_putc( char c, FILE *t ) +{ + Serial.write( c ); + + return c; +} + +void printf_begin(void) +{ + fdevopen( &serial_putc, 0 ); +} + +#endif // __PRINTF_H__