subree of RF24 merged

This commit is contained in:
Henrik Ekblad
2014-05-01 00:16:07 +02:00
parent 1897409bde
commit ab3bad4b1c
80 changed files with 18009 additions and 0 deletions
@@ -0,0 +1,136 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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.
//2014 - TMRh20 - Updated along with Optimized RF24 Library fork
*/
/**
* Example for Getting Started with nRF24L01+ radios.
*
* This is an example of how to use the RF24 class to communicate on a basic level. Write this sketch to two
* different nodes. Put one of the nodes into 'transmit' mode by connecting with the serial monitor and
* sending a 'T'. The ping node sends the current time to the pong node, which responds by sending the value
* back. The ping node can then see how long the whole cycle took.
* Note: For a more efficient call-response scenario see the GettingStarted_CallResponse.ino example.
* Note: When switching between sketches, the radio may need to be powered down to clear settings that are not "un-set" otherwise
*/
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
// Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(7,8);
const uint64_t addresses[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate.
// Set up roles to simplify testing
boolean role; // The main role variable, holds the current role identifier
boolean role_ping_out = 1, role_pong_back = 0; // The two different roles.
void setup() {
Serial.begin(57600);
printf_begin();
printf("\n\rRF24/examples/GettingStarted/\n\r");
printf("*** PRESS 'T' to begin transmitting to the other node\n\r");
// Setup and configure rf radio
radio.begin(); // Start up the radio
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.setRetries(15,15); // Max delay between retries & number of retries
radio.openWritingPipe(addresses[1]); // Open a writing pipe on pipe 0, with address 1
radio.openReadingPipe(1,addresses[0]); // Open a reading pipe on pipe 1, with address 0
radio.startListening(); // Start listening
radio.printDetails(); // Dump the configuration of the rf unit for debugging
}
void loop(void){
/****************** Ping Out Role ***************************/
if (role == role_ping_out) {
radio.stopListening(); // First, stop listening so we can talk.
printf("Now sending \n\r");
unsigned long time = micros(); // Take the time, and send it. This will block until complete
if (!radio.write( &time, sizeof(unsigned long) )){ printf("failed.\n\r"); }
radio.startListening(); // Now, continue listening
unsigned long started_waiting_at = micros(); // Set up a timeout period, get the current microseconds
boolean timeout = false; // Set up a variable to indicate if a response was received or not
while ( ! radio.available() ){ // While nothing is received
if (micros() - started_waiting_at > 200000 ){ // If waited longer than 200ms, indicate timeout and exit while loop
timeout = true;
break;
}
}
if ( timeout ){ // Describe the results
printf("Failed, response timed out.\n\r");
}else{
unsigned long got_time; // Grab the response, compare, and send to debugging spew
radio.read( &got_time, sizeof(unsigned long) );
// Spew it
printf("Sent %lu, Got response %lu, round-trip delay: %lu microseconds\n\r",time,got_time,micros()-got_time);
}
// Try again 1s later
delay(1000);
}
/****************** Pong Back Role ***************************/
if ( role == role_pong_back )
{
if( radio.available()){
unsigned long got_time; // Variable for the received timestamp
while (radio.available()) { // While there is data ready
radio.read( &got_time, sizeof(unsigned long) ); // Get the payload
}
radio.stopListening(); // First, stop listening so we can talk
radio.write( &got_time, sizeof(unsigned long) ); // Send the final one back.
radio.startListening(); // Now, resume listening so we catch the next packets.
printf("Sent response %lu \n\r", got_time);
}
}
/****************** Change Roles via Serial Commands ***************************/
if ( Serial.available() )
{
char c = toupper(Serial.read());
if ( c == 'T' && role == role_pong_back )
{
printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r");
role = role_ping_out; // Become the primary transmitter (ping out)
radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(1,addresses[1]);
}
else if ( c == 'R' && role == role_ping_out )
{
printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r");
role = role_pong_back; // Become the primary receiver (pong back)
radio.openWritingPipe(addresses[1]);
radio.openReadingPipe(1,addresses[0]);
}
}
}
@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__
@@ -0,0 +1,124 @@
/*
March 2014 - TMRh20 - Updated along with High Speed RF24 Library fork
Parts derived from examples by J. Coliz <maniacbug@ymail.com>
*/
/**
* Example for efficient call-response using ack-payloads
*
* This example continues to make use of all the normal functionality of the radios including
* the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
* This allows very fast call-response communication, with the responding radio never having to
* switch out of Primary Receiver mode to send back a payload, but having the option to switch to
* primary transmitter if wanting to initiate communication instead of respond to a commmunication.
*/
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
// Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(7,8);
// Topology
const uint64_t addresses[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate.
// Role management: Set up role. This sketch uses the same software for all the nodes
// in this system. Doing so greatly simplifies testing.
typedef enum { role_ping_out = 1, role_pong_back } role_e; // The various roles supported by this sketch
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; // The debug-friendly names of those roles
role_e role = role_pong_back; // The role of the current running sketch
byte counter = 1; // A single byte to keep track of the data being sent back and forth
void setup(){
Serial.begin(57600);
printf_begin();
printf("\n\rRF24/examples/GettingStarted/\n\r");
printf("ROLE: %s\n\r",role_friendly_name[role]);
printf("*** PRESS 'T' to begin transmitting to the other node\n\r");
// Setup and configure radio
radio.begin();
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.enableAckPayload(); // Allow optional ack payloads
radio.setRetries(0,15); // Smallest time between retries, max no. of retries
radio.setPayloadSize(1); // Here we are sending 1-byte payloads to test the call-response speed
radio.openWritingPipe(addresses[1]); // Both radios listen on the same pipes by default, and switch when writing
radio.openReadingPipe(1,addresses[0]); // Open a reading pipe on address 0, pipe 1
radio.startListening(); // Start listening
radio.powerUp();
radio.printDetails(); // Dump the configuration of the rf unit for debugging
}
void loop(void) {
/****************** Ping Out Role ***************************/
if (role == role_ping_out){ // Radio is in ping mode
byte gotByte; // Initialize a variable for the incoming response
radio.stopListening(); // First, stop listening so we can talk.
printf("Now sending %d as payload. ",counter); // Use a simple byte counter as payload
unsigned long time = micros(); // Record the current microsecond count
if ( radio.write(&counter,1) ){ // Send the counter variable to the other radio
if(!radio.available()){ // If nothing in the buffer, we got an ack but it is blank
printf("Got blank response. round-trip delay: %lu microseconds\n\r",micros()-time);
}else{
while(radio.available() ){ // If an ack with payload was received
radio.read( &gotByte, 1 ); // Read it, and display the response time
printf("Got response %d, round-trip delay: %lu microseconds\n\r",gotByte,micros()-time);
counter++; // Increment the counter variable
}
}
}else{ printf("Sending failed.\n\r"); } // If no ack response, sending failed
delay(1000); // Try again later
}
/****************** Pong Back Role ***************************/
if ( role == role_pong_back ) {
byte pipeNo, gotByte; // Declare variables for the pipe and the byte received
while( radio.available(&pipeNo)){ // Read all available payloads
radio.read( &gotByte, 1 );
// Since this is a call-response. Respond directly with an ack payload.
// Ack payloads are much more efficient than switching to transmit mode to respond to a call
radio.writeAckPayload(pipeNo,&gotByte, 1 ); // This can be commented out to send empty payloads.
printf("Sent response %d \n\r", gotByte);
}
}
/****************** Change Roles via Serial Commands ***************************/
if ( Serial.available() )
{
char c = toupper(Serial.read());
if ( c == 'T' && role == role_pong_back )
{
printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r");
role = role_ping_out; // Change roles (ping out)
radio.openWritingPipe(addresses[0]); // Open different pipes when writing. Write on pipe 0, address 0
radio.openReadingPipe(1,addresses[1]); // Read on pipe 1, as address 1
}
else if ( c == 'R' && role == role_ping_out )
{
printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r");
role = role_pong_back; // Become the primary receiver (pong back)
radio.openWritingPipe(addresses[1]); // Since only two radios involved, both listen on the same addresses and pipe numbers in RX mode
radio.openReadingPipe(1,addresses[0]); // then switch pipes & addresses to transmit.
radio.startListening(); // Need to start listening after opening new reading pipes
}
}
}
@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__
@@ -0,0 +1,144 @@
/*
TMRh20 2014
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.
*/
/** General Data Transfer Rate Test
* This example demonstrates basic data transfer functionality with the
updated library. This example will display the transfer rates acheived using
the slower form of high-speed transfer using blocking-writes.
*/
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
/************* USER Configuration *****************************/
// Hardware configuration
RF24 radio(48,49); // Set up nRF24L01 radio on SPI bus plus pins 7 & 8
boolean RADIO_NO = 0; //SET THIS TO 0 or 1 for 1st or 2nd radio
/***************************************************************/
const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate.
byte data[32]; //Data buffer for testing data transfer speeds
unsigned long counter, rxTimer; //Counter and timer for keeping track transfer info
unsigned long startTime, stopTime;
bool TX=1,RX=0,role=0;
void setup(void) {
Serial.begin(57600);
printf_begin();
radio.begin(); // Setup and configure rf radio
radio.setChannel(1);
radio.setPALevel(RF24_PA_MAX);
radio.setDataRate(RF24_1MBPS);
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.setRetries(2,15); // Optionally, increase the delay between retries & # of retries
radio.setCRCLength(RF24_CRC_8);
//radio.disableCRC();
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1,pipes[1]);
radio.startListening(); // Start listening
radio.printDetails(); // Dump the configuration of the rf unit for debugging
printf("\n\rRF24/examples/Transfer Rates/\n\r");
printf("*** PRESS 'T' to begin transmitting to the other node\n\r");
randomSeed(analogRead(0)); //Seed for random number generation
for(int i=0; i<32; i++){
data[i] = random(255); //Load the buffer with random data
}
radio.powerUp(); //Power up the radio
}
void loop(void){
if(role == TX){
delay(2000);
printf("Initiating Basic Data Transfer\n\r");
unsigned long cycles = 10000; //Change this to a higher or lower number.
startTime = millis();
for(int i=0; i<cycles; i++){ //Loop through a number of cycles
data[0] = i; //Change the first byte of the payload for identification
if(!radio.writeFast(&data,32)){ //Write to the FIFO buffers
counter++; //Keep count of failed payloads
}
}
stopTime = millis();
//This should be called to wait for completion and put the radio in standby mode after transmission, returns 0 if data still in FIFO (timed out), 1 if success
if(!radio.txStandBy()){ counter+=3; } //Standby, block only until FIFO empty or auto-retry timeout. Flush TX FIFO if failed
//radio.txStandBy(1000); //Standby, using extended timeout period of 1 second
float numBytes = cycles*32;
float rate = numBytes / (stopTime - startTime);
printf("Transfer complete at "); Serial.print(rate); printf(" KB/s \n\r");
printf("%d of ",counter); Serial.print(cycles); printf(" Packets Failed to Send\n\r");
counter = 0;
}
if(role == RX){
while(radio.available()){
radio.read(&data,32);
counter++;
}
if(millis() - rxTimer > 1000){
rxTimer = millis();
printf("Rate: ");
float numBytes = counter*32;
Serial.print(numBytes/1000);
printf(" KB/s\n\r");
printf("Payload Count: %d \n\r", counter);
counter = 0;
}
}
//
// Change roles
//
if ( Serial.available() )
{
char c = toupper(Serial.read());
if ( c == 'T' && role == RX )
{
printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r");
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
radio.stopListening();
role = TX; // Become the primary transmitter (ping out)
}
else if ( c == 'R' && role == TX )
{
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1,pipes[1]);
radio.startListening();
printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r");
role = RX; // Become the primary receiver (pong back)
}
}
}
// vim:cin:ai:sts=2 sw=2 ft=cpp
+37
View File
@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__
@@ -0,0 +1,189 @@
/*
TMRh20 2014
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.
*/
/** Reliably transmitting large volumes of data with a low signal or in noisy environments
* This example demonstrates data transfer functionality with the use of auto-retry
and auto-reUse functionality enabled. This sketch demonstrates how a user can extend
the auto-retry functionality to any chosen time period, preventing data loss and ensuring
the consistency of data.
This sketh demonstrates use of the writeBlocking() functionality, and extends the standard
retry functionality of the radio. Payloads will be auto-retried until successful or the
extended timeout period is reached.
*/
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
/************* USER Configuration *****************************/
RF24 radio(48,49); // Set up nRF24L01 radio on SPI bus plus pins 7 & 8
unsigned long timeoutPeriod = 3000; // Set a user-defined timeout period. With auto-retransmit set to (15,15) retransmission will take up to 60ms and as little as 7.5ms with it set to (1,15).
// With a timeout period of 1000, the radio will retry each payload for up to 1 second before giving up on the transmission and starting over
/***************************************************************/
const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate.
byte data[32]; //Data buffer
volatile unsigned long counter;
unsigned long rxTimer,startTime, stopTime, payloads = 0;
bool TX=1,RX=0,role=0, transferInProgress = 0;
void setup(void) {
Serial.begin(57600);
printf_begin();
radio.begin(); // Setup and configure rf radio
radio.setChannel(1); // Set the channel
radio.setPALevel(RF24_PA_LOW); // Set PA LOW for this demonstration. We want the radio to be as lossy as possible for this example.
radio.setDataRate(RF24_1MBPS); // Raise the data rate to reduce transmission distance and increase lossiness
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.setRetries(2,15); // Optionally, increase the delay between retries. Want the number of auto-retries as high as possible (15)
radio.setCRCLength(RF24_CRC_16); // Set CRC length to 16-bit to ensure quality of data
radio.openWritingPipe(pipes[0]); // Open the default reading and writing pipe
radio.openReadingPipe(1,pipes[1]);
radio.startListening(); // Start listening
radio.printDetails(); // Dump the configuration of the rf unit for debugging
printf("\n\rRF24/examples/Transfer Rates/\n\r");
printf("*** PRESS 'T' to begin transmitting to the other node\n\r");
randomSeed(analogRead(0)); //Seed for random number generation
for(int i=0; i<32; i++){
data[i] = random(255); //Load the buffer with random data
}
radio.powerUp(); //Power up the radio
}
void loop(void){
if(role == TX){
delay(2000); // Pause for a couple seconds between transfers
printf("Initiating Extended Timeout Data Transfer\n\r");
unsigned long cycles = 1000; // Change this to a higher or lower number. This is the number of payloads that will be sent.
unsigned long transferCMD[] = {'H','S',cycles }; // Indicate to the other radio that we are starting, and provide the number of payloads that will be sent
radio.writeFast(&transferCMD,12); // Send the transfer command
if(radio.txStandBy(timeoutPeriod)){ // If transfer initiation was successful, do the following
startTime = millis(); // For calculating transfer rate
boolean timedOut = 0; // Boolean for keeping track of failures
for(int i=0; i<cycles; i++){ // Loop through a number of cycles
data[0] = i; // Change the first byte of the payload for identification
if(!radio.writeBlocking(&data,32,timeoutPeriod)){ // If retries are failing and the user defined timeout is exceeded
timedOut = 1; // Indicate failure
counter = cycles; // Set the fail count to maximum
break; // Break out of the for loop
}
}
stopTime = millis(); // Capture the time of completion or failure
//This should be called to wait for completion and put the radio in standby mode after transmission, returns 0 if data still in FIFO (timed out), 1 if success
if(timedOut){ radio.txStandBy(); } //Partially blocking standby, blocks until success or max retries. FIFO flushed if auto timeout reached
else{ radio.txStandBy(timeoutPeriod); } //Standby, block until FIFO empty (sent) or user specified timeout reached. FIFO flushed if user timeout reached.
}else{
Serial.println("Communication not established"); //If unsuccessful initiating transfer, exit and retry later
}
float rate = cycles * 32 / (stopTime - startTime); //Display results:
Serial.print("Transfer complete at "); Serial.print(rate); printf(" KB/s \n\r");
Serial.print(counter);
Serial.print(" of ");
Serial.print(cycles); Serial.println(" Packets Failed to Send");
counter = 0;
}
if(role == RX){
if(!transferInProgress){ // If a bulk data transfer has not been started
if(radio.available()){
radio.read(&data,32); //Read any available payloads for analysis
if(data[0] == 'H' && data[4] == 'S'){ // If a bulk data transfer command has been received
payloads = data[8]; // Read the first two bytes of the unsigned long. Need to read the 3rd and 4th if sending more than 65535 payloads
payloads |= data[9] << 8; // This is the number of payloads that will be sent
counter = 0; // Reset the payload counter to 0
transferInProgress = 1; // Indicate it has started
startTime = rxTimer = millis(); // Capture the start time to measure transfer rate and calculate timeouts
}
}
}else{
if(radio.available()){ // If in bulk transfer mode, and a payload is available
radio.read(&data,32); // Read the payload
rxTimer = millis(); // Reset the timeout timer
counter++; // Keep a count of received payloads
}else
if(millis() - rxTimer > timeoutPeriod){ // If no data available, check the timeout period
Serial.println("Transfer Failed"); // If per-payload timeout exceeeded, end the transfer
transferInProgress = 0;
}else
if(counter >= payloads){ // If the specified number of payloads is reached, transfer is completed
startTime = millis() - startTime; // Calculate the total time spent during transfer
float numBytes = counter*32; // Calculate the number of bytes transferred
Serial.print("Rate: "); // Print the transfer rate and number of payloads
Serial.print(numBytes/startTime);
Serial.println(" KB/s");
printf("Payload Count: %d \n\r", counter);
transferInProgress = 0; // End the transfer as complete
}
}
}
//
// Change roles
//
if ( Serial.available() )
{
char c = toupper(Serial.read());
if ( c == 'T' && role == RX )
{
printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r");
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
radio.stopListening();
role = TX; // Become the primary transmitter (ping out)
}
else if ( c == 'R' && role == TX )
{
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1,pipes[1]);
radio.startListening();
printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r");
role = RX; // Become the primary receiver (pong back)
}
}
}
@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__
@@ -0,0 +1,206 @@
PROJECT_NAME = $(PWD:B) ;
PROJECT_DIR = . ;
PROJECT_LIBS = SPI RF24 ;
OUT_DIR = ojam ;
F_CPU = 16000000 ;
MCU = atmega328p ;
PORTS = /dev/tty.usbserial-A600eHIs /dev/tty.usbserial-A40081RP /dev/tty.usbserial-A9007LmI ;
UPLOAD_RATE = 57600 ;
AVRDUDE_PROTOCOL = stk500v1 ;
COM = 33 ;
# Host-specific overrides for locations
if $(OS) = MACOSX
{
ARDUINO_VERSION = 22 ;
OLD_DIR = /opt/arduino-0021 ;
AVR_TOOLS_PATH = $(OLD_DIR)/hardware/tools/avr/bin ;
AVRDUDECONFIG_PATH = $(OLD_DIR)/hardware/tools/avr/etc ;
ARDUINO_DIR = /opt/Arduino ;
ARDUINO_AVR = /usr/lib/avr/include ;
}
# Where is everything?
ARDUINO_VERSION ?= 22 ;
AVR_TOOLS_PATH ?= /usr/bin ;
ARDUINO_DIR ?= /opt/arduino-00$(ARDUINO_VERSION) ;
ARDUINO_AVR ?= $(ARDUINO_DIR)/hardware/tools/avr/avr/include/avr ;
AVRDUDECONFIG_PATH ?= $(ARDUINO_DIR)/hardware/tools ;
ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino ;
ARDUINO_LIB = $(ARDUINO_DIR)/libraries ;
SKETCH_LIB = $(HOME)/Source/Arduino/libraries ;
AVR_CC = $(AVR_TOOLS_PATH)/avr-gcc ;
AVR_CXX = $(AVR_TOOLS_PATH)/avr-g++ ;
AVR_LD = $(AVR_TOOLS_PATH)/avr-gcc ;
AVR_OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy ;
AVRDUDE = $(AVR_TOOLS_PATH)/avrdude ;
DEFINES = F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ;
CTUNING = -ffunction-sections -fdata-sections ;
CXXTUNING = -fno-exceptions -fno-strict-aliasing ;
CFLAGS = -Os -Wall -Wextra -mmcu=$(MCU) $(CTUNING) ;
CXXFLAGS = $(CFLAGS) $(CXXTUNING) ;
LDFLAGS = -Os -lm -Wl,--gc-sections -mmcu=atmega328p ;
# Search everywhere for headers
HDRS = $(PROJECT_DIR) $(ARDUINO_AVR) $(ARDUINO_CORE) [ GLOB $(ARDUINO_LIB) $(SKETCH_LIB) : [^.]* ] ;
# Grab everything from the core directory
CORE_MODULES = [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ;
# Grab everything from libraries. To avoid this "grab everything" behaviour, you
# can specify specific modules to pick up in PROJECT_MODULES
LIB_MODULES = [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp ] ;
# In addition to explicitly-specified program modules, pick up anything from the current
# dir.
PROJECT_MODULES += [ GLOB $(PROJECT_DIR) : *.c *.cpp *.pde ] ;
# Shortcut for the out files
OUT = $(OUT_DIR)/$(PROJECT_NAME) ;
# AvrDude setup
AVRDUDE_FLAGS = -V -F -D -C $(AVRDUDECONFIG_PATH)/avrdude.conf -p $(MCU) -c $(AVRDUDE_PROTOCOL) -b $(UPLOAD_RATE) ;
rule GitVersion
{
Always $(<) ;
Depends all : $(<) ;
}
actions GitVersion
{
echo "const char program_version[] = \"\\" > $(<)
git log -1 --pretty=format:%h >> $(<)
echo "\";" >> $(<)
}
GitVersion version.h ;
rule AvrCc
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Clean clean : $(<) ;
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions AvrCc
{
$(AVR_CC) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CFLAGS) $(>)
}
rule AvrC++
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Clean clean : $(<) ;
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions AvrC++
{
$(AVR_CXX) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CXXFLAGS) $(>)
}
rule Pde
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Clean clean : $(<) ;
}
actions Pde
{
echo "#include <WProgram.h>" > $(<)
echo "#line 1 \"$(>)\"" >> $(<)
cat $(>) >> $(<)
}
rule AvrPde
{
local _CPP = $(OUT_DIR)/$(_I:B).cpp ;
Pde $(_CPP) : $(>) ;
AvrC++ $(<) : $(_CPP) ;
}
rule AvrObject
{
switch $(>:S)
{
case .c : AvrCc $(<) : $(>) ;
case .cpp : AvrC++ $(<) : $(>) ;
case .pde : AvrPde $(<) : $(>) ;
}
}
rule AvrObjects
{
for _I in $(<)
{
AvrObject $(OUT_DIR)/$(_I:B).o : $(_I) ;
}
}
rule AvrMainFromObjects
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
MkDir $(<:D) ;
Depends all : $(<) ;
Clean clean : $(<) ;
}
actions AvrMainFromObjects
{
$(AVR_LD) $(LDFLAGS) -o $(<) $(>)
}
rule AvrMain
{
AvrMainFromObjects $(<) : $(OUT_DIR)/$(>:B).o ;
AvrObjects $(>) ;
}
rule AvrHex
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Depends hex : $(<) ;
Clean clean : $(<) ;
}
actions AvrHex
{
$(AVR_OBJCOPY) -O ihex -R .eeprom $(>) $(<)
}
rule AvrUpload
{
Depends $(1) : $(2) ;
Depends $(2) : $(3) ;
NotFile $(1) ;
Always $(1) ;
Always $(2) ;
AvrUploadAction $(2) : $(3) ;
}
actions AvrUploadAction
{
$(AVRDUDE) $(AVRDUDE_FLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i
}
AvrMain $(OUT).elf : $(CORE_MODULES) $(LIB_MODULES) $(PROJECT_MODULES) ;
AvrHex $(OUT).hex : $(OUT).elf ;
AvrUpload p6 : /dev/tty.usbserial-A600eHIs : $(OUT).hex ;
AvrUpload p4 : /dev/tty.usbserial-A40081RP : $(OUT).hex ;
AvrUpload p9 : /dev/tty.usbserial-A9007LmI : $(OUT).hex ;
@@ -0,0 +1,255 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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 <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
//
// Hardware configuration
//
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
// 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];
uint8_t led_states[num_led_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(57600);
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_led_pins;
while(i--)
{
pinMode(led_pins[i],OUTPUT);
led_states[i] = HIGH;
digitalWrite(led_pins[i],led_states[i]);
}
}
}
//
// 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
bool 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");
// For each button, if the button now on, then toggle the LED
int i = num_led_pins;
while(i--)
{
if ( button_states[i] )
{
led_states[i] ^= HIGH;
digitalWrite(led_pins[i],led_states[i]);
}
}
}
}
}
}
// vim:ai:cin:sts=2 sw=2 ft=cpp
@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__
@@ -0,0 +1,219 @@
# (1) Project Information
PROJECT_LIBS = RF24 SPI ;
PROJECT_DIRS = $(PWD) ;
# (2) Board Information
UPLOAD_PROTOCOL ?= stk500v1 ;
UPLOAD_SPEED ?= 115200 ;
MCU ?= atmega328p ;
F_CPU ?= 16000000 ;
CORE ?= arduino ;
VARIANT ?= standard ;
ARDUINO_VERSION ?= 100 ;
# (3) USB Ports
PORTS = p4 p6 p9 u0 u1 u2 ;
PORT_p6 = /dev/tty.usbserial-A600eHIs ;
PORT_p4 = /dev/tty.usbserial-A40081RP ;
PORT_p9 = /dev/tty.usbserial-A9007LmI ;
PORT_u0 = /dev/ttyUSB0 ;
PORT_u1 = /dev/ttyUSB1 ;
PORT_u2 = /dev/ttyUSB2 ;
# (4) Location of AVR tools
#
# This configuration assumes using avr-tools that were obtained separate from the Arduino
# distribution.
if $(OS) = MACOSX
{
AVR_BIN = /usr/local/avrtools/bin ;
AVR_ETC = /usr/local/avrtools/etc ;
AVR_INCLUDE = /usr/local/avrtools/include ;
}
else
{
AVR_BIN = /usr/bin ;
AVR_INCLUDE = /usr/lib/avr/include ;
AVR_ETC = /etc ;
}
# (5) Directories where Arduino core and libraries are located
ARDUINO_DIR ?= /opt/Arduino ;
ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/$(CORE) $(ARDUINO_DIR)/hardware/arduino/variants/$(VARIANT) ;
ARDUINO_LIB = $(ARDUINO_DIR)/libraries ;
SKETCH_LIB = $(HOME)/Source/Arduino/libraries ;
#
# --------------------------------------------------
# Below this line usually never needs to be modified
#
# Tool locations
CC = $(AVR_BIN)/avr-gcc ;
C++ = $(AVR_BIN)/avr-g++ ;
LINK = $(AVR_BIN)/avr-gcc ;
AR = $(AVR_BIN)/avr-ar rcs ;
RANLIB = ;
OBJCOPY = $(AVR_BIN)/avr-objcopy ;
AVRDUDE = $(AVR_BIN)/avrdude ;
# Flags
DEFINES += F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ;
OPTIM = -Os ;
CCFLAGS = -Wall -Wextra -Wno-strict-aliasing -mmcu=$(MCU) -ffunction-sections -fdata-sections ;
C++FLAGS = $(CCFLAGS) -fno-exceptions -fno-strict-aliasing ;
LINKFLAGS = $(OPTIM) -lm -Wl,--gc-sections -mmcu=$(MCU) ;
AVRDUDEFLAGS = -V -F -D -C $(AVR_ETC)/avrdude.conf -p $(MCU) -c $(UPLOAD_PROTOCOL) -b $(UPLOAD_SPEED) ;
# Search everywhere for headers
HDRS = $(PROJECT_DIRS) $(AVR_INCLUDE) $(ARDUINO_CORE) $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) ;
# Output locations
LOCATE_TARGET = $(F_CPU) ;
LOCATE_SOURCE = $(F_CPU) ;
#
# Custom rules
#
rule GitVersion
{
Always $(<) ;
Depends all : $(<) ;
}
actions GitVersion
{
echo "const char program_version[] = \"\\" > $(<)
git log -1 --pretty=format:%h >> $(<)
echo "\";" >> $(<)
}
GitVersion version.h ;
rule Pde
{
Depends $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_SOURCE) ;
Clean clean : $(<) ;
}
if ( $(ARDUINO_VERSION) < 100 )
{
ARDUINO_H = WProgram.h ;
}
else
{
ARDUINO_H = Arduino.h ;
}
actions Pde
{
echo "#include <$(ARDUINO_H)>" > $(<)
echo "#line 1 \"$(>)\"" >> $(<)
cat $(>) >> $(<)
}
rule C++Pde
{
local _CPP = $(>:B).cpp ;
Pde $(_CPP) : $(>) ;
C++ $(<) : $(_CPP) ;
}
rule UserObject
{
switch $(>:S)
{
case .ino : C++Pde $(<) : $(>) ;
case .pde : C++Pde $(<) : $(>) ;
}
}
rule Objects
{
local _i ;
for _i in [ FGristFiles $(<) ]
{
local _b = $(_i:B)$(SUFOBJ) ;
local _o = $(_b:G=$(SOURCE_GRIST:E)) ;
Object $(_o) : $(_i) ;
Depends obj : $(_o) ;
}
}
rule Library
{
LibraryFromObjects $(<) : $(>:B)$(SUFOBJ) ;
Objects $(>) ;
}
rule Main
{
MainFromObjects $(<) : $(>:B)$(SUFOBJ) ;
Objects $(>) ;
}
rule Hex
{
Depends $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_TARGET) ;
Depends hex : $(<) ;
Clean clean : $(<) ;
}
actions Hex
{
$(OBJCOPY) -O ihex -R .eeprom $(>) $(<)
}
rule Upload
{
Depends $(1) : $(2) ;
Depends $(2) : $(3) ;
NotFile $(1) ;
Always $(1) ;
Always $(2) ;
UploadAction $(2) : $(3) ;
}
actions UploadAction
{
$(AVRDUDE) $(AVRDUDEFLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i
}
rule Arduino
{
LINKFLAGS on $(<) = $(LINKFLAGS) -Wl,-Map=$(LOCATE_TARGET)/$(<:B).map ;
Main $(<) : $(>) ;
LinkLibraries $(<) : libs core ;
Hex $(<:B).hex : $(<) ;
for _p in $(PORTS)
{
Upload $(_p) : $(PORT_$(_p)) : $(<:B).hex ;
}
}
#
# Targets
#
# Grab everything from the core directory
Library core : [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ;
# Grab everything from libraries. To avoid this "grab everything" behaviour, you
# can specify specific modules to pick up in PROJECT_MODULES
Library libs : [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp *.c ] ;
# Main output executable
Arduino $(PWD:B).elf : $(PROJECT_MODULES) [ GLOB $(PROJECT_DIRS) : *.c *.cpp *.pde *.ino ] ;
@@ -0,0 +1,142 @@
/*
Copyright (C) 2012 J. Coliz <maniacbug@ymail.com>
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 Nordic FOB Receiver
*
* This is an example of how to use the RF24 class to receive signals from the
* Sparkfun Nordic FOB. Thanks to Kirk Mower for providing test hardware.
*
* See blog post at http://maniacbug.wordpress.com/2012/01/08/nordic-fob/
*/
#include <SPI.h>
#include <RF24.h>
#include "nRF24L01.h"
#include "printf.h"
//
// Hardware configuration
//
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
//
// Payload
//
struct payload_t
{
uint8_t buttons;
uint16_t id;
uint8_t empty;
};
const char* button_names[] = { "Up", "Down", "Left", "Right", "Center" };
const int num_buttons = 5;
//
// Forward declarations
//
uint16_t flip_endian(uint16_t in);
//
// Setup
//
void setup(void)
{
//
// Print preamble
//
Serial.begin(57600);
printf_begin();
printf("\r\nRF24/examples/nordic_fob/\r\n");
//
// Setup and configure rf radio according to the built-in parameters
// of the FOB.
//
radio.begin();
radio.setChannel(2);
radio.setPayloadSize(4);
radio.setAutoAck(false);
radio.setCRCLength(RF24_CRC_8);
radio.openReadingPipe(1,0xE7E7E7E7E7LL);
//
// Start listening
//
radio.startListening();
//
// Dump the configuration of the rf unit for debugging
//
radio.printDetails();
}
//
// Loop
//
void loop(void)
{
//
// Receive each packet, dump it out
//
// if there is data ready
if ( radio.available() )
{
// Get the packet from the radio
payload_t payload;
radio.read( &payload, sizeof(payload) );
// Print the ID of this message. Note that the message
// is sent 'big-endian', so we have to flip it.
printf("#%05u Buttons ",flip_endian(payload.id));
// Print the name of each button
int i = num_buttons;
while (i--)
{
if ( ! ( payload.buttons & _BV(i) ) )
{
printf("%s ",button_names[i]);
}
}
// If no buttons, print None
if ( payload.buttons == _BV(num_buttons) - 1 )
printf("None");
printf("\r\n");
}
}
//
// Helper functions
//
// Change a big-endian word into a little-endian
uint16_t flip_endian(uint16_t in)
{
uint16_t low = in >> 8;
uint16_t high = in << 8;
return high | low;
}
// vim:cin:ai:sts=2 sw=2 ft=cpp
@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__
@@ -0,0 +1,182 @@
MCU = cortex-m3 ;
CHIP = STM32F103ZE ;
BOARD = maple_native ;
#CHIP = at91sam3u4 ;
#BOARD = sam3u-ek ;
if ! $(TOOLSET)
{
TOOLSET = devkit ;
Echo "Assuming TOOLSET=devkit" ;
}
if $(TOOLSET) = yagarto
{
TOOLS_PATH = ~/Source/yagarto-4.6.2/bin ;
TOOLS_ARCH = arm-none-eabi- ;
}
if $(TOOLSET) = yagarto-install
{
TOOLS_PATH = ~/Source/yagarto/install/bin ;
TOOLS_ARCH = arm-none-eabi- ;
}
else if $(TOOLSET) = devkit
{
TOOLS_PATH = /opt/devkitARM/bin ;
TOOLS_ARCH = arm-eabi- ;
}
else if $(TOOLSET) = maple
{
TOOLS_PATH = /opt/Maple/Resources/Java/hardware/tools/arm/bin ;
TOOLS_ARCH = arm-none-eabi- ;
}
else if $(TOOLSET) = ports
{
TOOLS_PATH = /opt/local/bin ;
TOOLS_ARCH = arm-none-eabi- ;
}
CC = $(TOOLS_PATH)/$(TOOLS_ARCH)gcc ;
C++ = $(TOOLS_PATH)/$(TOOLS_ARCH)g++ ;
AS = $(TOOLS_PATH)/$(TOOLS_ARCH)gcc -c ;
LINK = $(TOOLS_PATH)/$(TOOLS_ARCH)g++ ;
OBJCOPY = $(TOOLS_PATH)/$(TOOLS_ARCH)objcopy ;
DFU = dfu-util ;
DEFINES += VECT_TAB_FLASH BOARD_$(BOARD) MCU_$(CHIP) ERROR_LED_PORT=GPIOC ERROR_LED_PIN=15 STM32_HIGH_DENSITY MAPLE_IDE ;
OPTIM = -Os ;
MFLAGS = cpu=$(MCU) thumb arch=armv7-m ;
CCFLAGS = -Wall -m$(MFLAGS) -g -nostdlib -ffunction-sections -fdata-sections -Wl,--gc-sections ;
C++FLAGS = $(CCFLAGS) -fno-rtti -fno-exceptions ;
LINKFLAGS += -m$(MFLAGS) -Xlinker --gc-sections ;
DFUFLAGS = -a1 -d 0x1eaf:0x0003 -R ;
MAPLE_DIR = $(HOME)/Source/SAM3U/libmaple ;
MAPLE_LIBS = Servo LiquidCrystal Wire FreeRTOS ;
MAPLE_SUBDIRS = wirish wirish/comm wirish/boards libmaple libmaple/usb libmaple/usb/usb_lib ;
SKETCH_DIR = $(HOME)/Source/Arduino ;
SKETCH_LIBS = RF24 ;
MODULE_DIRS = . $(MAPLE_DIR)/$(MAPLE_SUBDIRS) $(MAPLE_DIR)/libraries/$(MAPLE_LIBS) $(SKETCH_DIR)/libraries/$(SKETCH_LIBS) ;
HDRS = $(MODULE_DIRS) ;
LOCATE_TARGET = out/$(TOOLSET) ;
LOCATE_SOURCE = $(LOCATE_TARGET) ;
rule Pde
{
Depends $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_SOURCE) ;
Clean clean : $(<) ;
}
if ( $(ARDUINO_VERSION) < 100 )
{
ARDUINO_H = WProgram.h ;
}
else
{
ARDUINO_H = Arduino.h ;
}
actions Pde
{
echo "#include <$(ARDUINO_H)>" > $(<)
echo "#line 1 \"$(>)\"" >> $(<)
cat $(>) >> $(<)
}
rule C++Pde
{
local _CPP = $(>:B).cpp ;
Pde $(_CPP) : $(>) ;
C++ $(<) : $(_CPP) ;
}
rule Hex
{
Depends $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_TARGET) ;
Depends hex : $(<) ;
Clean clean : $(<) ;
}
actions Hex
{
$(OBJCOPY) -O ihex $(>) $(<)
}
rule Binary
{
Depends $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_TARGET) ;
Depends binary : $(<) ;
Clean clean : $(<) ;
}
actions Binary
{
$(OBJCOPY) -O binary $(>) $(<)
}
rule UserObject
{
switch $(>:S)
{
case .S : As $(<) : $(>) ;
case .ino : C++Pde $(<) : $(>) ;
case .pde : C++Pde $(<) : $(>) ;
}
}
rule Upload
{
Depends up : $(<) ;
NotFile up ;
Always $(<) ;
Always up ;
}
actions Upload
{
$(DFU) $(DFUFLAGS) -D $(<)
}
# Override base objects rule, so all output can go in the output dir
rule Objects
{
local _i ;
for _i in [ FGristFiles $(<) ]
{
local _b = $(_i:B)$(SUFOBJ) ;
local _o = $(_b:G=$(SOURCE_GRIST:E)) ;
Object $(_o) : $(_i) ;
Depends obj : $(_o) ;
}
}
# Override base main rule, so all output can go in the output dir
rule Main
{
MainFromObjects $(<) : $(>:B)$(SUFOBJ) ;
Objects $(>) ;
}
# Modules
MODULES = [ GLOB $(MODULE_DIRS) : *.pde *.c *.cpp *.S ] ;
# Main output executable
MAIN = $(PWD:B).elf ;
# Linker script
LINK_DIR = $(MAPLE_DIR)/support/ld ;
LINKSCRIPT = $(LINK_DIR)/$(BOARD)/flash.ld ;
# Bring in the map and link script
LINKFLAGS += -Wl,-Map=$(LOCATE_TARGET)/$(MAIN:B).map -T$(LINKSCRIPT) -L$(LINK_DIR) ;
Main $(MAIN) : $(MODULES) ;
Binary $(MAIN:B).bin : $(MAIN) ;
Upload $(MAIN:B).bin ;
@@ -0,0 +1,87 @@
#ifdef MAPLE_IDE
#include <stdio.h>
#include "wirish.h"
extern void setup(void);
extern void loop(void);
void board_start(const char* program_name)
{
// Set up the LED to steady on
pinMode(BOARD_LED_PIN, OUTPUT);
digitalWrite(BOARD_LED_PIN, HIGH);
// Setup the button as input
pinMode(BOARD_BUTTON_PIN, INPUT);
digitalWrite(BOARD_BUTTON_PIN, HIGH);
SerialUSB.begin();
SerialUSB.println("Press BUT");
// Wait for button press
while ( !isButtonPressed() )
{
}
SerialUSB.println("Welcome!");
SerialUSB.println(program_name);
int i = 11;
while (i--)
{
toggleLED();
delay(50);
}
}
/**
* Custom version of _write, which will print to the USB.
* In order to use it you MUST ADD __attribute__((weak))
* to _write in libmaple/syscalls.c
*/
extern "C" int _write (int file, char * ptr, int len)
{
if ( (file != 1) && (file != 2) )
return 0;
else
SerialUSB.write(ptr,len);
return len;
}
/**
* Re-entrant version of _write. Yagarto and Devkit now use
* the re-entrant newlib, so these get called instead of the
* non_r versions.
*/
extern "C" int _write_r (void*, int file, char * ptr, int len)
{
return _write( file, ptr, len);
}
__attribute__((constructor)) __attribute__ ((weak)) void premain()
{
init();
}
__attribute__((weak)) void setup(void)
{
board_start("No program defined");
}
__attribute__((weak)) void loop(void)
{
}
__attribute__((weak)) int main(void)
{
setup();
while (true)
{
loop();
}
return 0;
}
#endif // ifdef MAPLE_IDE
// vim:cin:ai:sts=2 sw=2 ft=cpp
@@ -0,0 +1,242 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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 RF Radio Ping Pair ... for Maple
*
* This is an example of how to use the RF24 class. Write this sketch to two different nodes,
* connect the role_pin to ground on one. The ping node sends the current time to the pong node,
* which responds by sending the value back. The ping node can then see how long the whole cycle
* took.
*/
#include "WProgram.h"
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
//
// Maple specific setup. Other than this section, the sketch is the same on Maple as on
// Arduino
//
#ifdef MAPLE_IDE
// External startup function
extern void board_start(const char* program_name);
// Use SPI #2.
HardwareSPI SPI(2);
#else
#define board_startup printf
#define toggleLED(x) (x)
#endif
//
// Hardware configuration
//
// Set up nRF24L01 radio on SPI bus plus pins 7 & 6
// (This works for the Getting Started board plugged into the
// Maple Native backwards.)
RF24 radio(7,6);
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
// Leave open to be the 'ping' transmitter
const int role_pin = 10;
//
// Topology
//
// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
//
// 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_ping_out = 1, role_pong_back } role_e;
// The debug-friendly names of those roles
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};
// The role of the current running sketch
role_e role;
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_ping_out;
else
role = role_pong_back;
//
// Print preamble
//
board_start("\n\rRF24/examples/pingpair/\n\r");
printf("ROLE: %s\n\r",role_friendly_name[role]);
//
// Setup and configure rf radio
//
radio.begin();
// optionally, increase the delay between retries & # of retries
radio.setRetries(15,15);
// optionally, reduce the payload size. seems to
// improve reliability
radio.setPayloadSize(8);
//
// Open pipes to other nodes for communication
//
// This simple sketch opens two pipes for these two nodes to communicate
// back and forth.
// Open 'our' pipe for writing
// Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)
if ( role == role_ping_out )
{
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1,pipes[1]);
}
else
{
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
}
//
// Start listening
//
radio.startListening();
//
// Dump the configuration of the rf unit for debugging
//
radio.printDetails();
}
void loop(void)
{
//
// Ping out role. Repeatedly send the current time
//
if (role == role_ping_out)
{
toggleLED();
// First, stop listening so we can talk.
radio.stopListening();
// Take the time, and send it. This will block until complete
unsigned long time = millis();
printf("Now sending %lu...",time);
bool ok = radio.write( &time, sizeof(unsigned long) );
if (ok)
printf("ok...\r\n");
else
printf("failed.\r\n");
// Now, continue listening
radio.startListening();
// Wait here until we get a response, or timeout (250ms)
unsigned long started_waiting_at = millis();
bool timeout = false;
while ( ! radio.available() && ! timeout )
if (millis() - started_waiting_at > 200 )
timeout = true;
// Describe the results
if ( timeout )
{
printf("Failed, response timed out.\r\n");
}
else
{
// Grab the response, compare, and send to debugging spew
unsigned long got_time;
radio.read( &got_time, sizeof(unsigned long) );
// Spew it
printf("Got response %lu, round-trip delay: %lu\r\n",got_time,millis()-got_time);
}
toggleLED();
// Try again 1s later
delay(1000);
}
//
// Pong back role. Receive each packet, dump it out, and send it back
//
if ( role == role_pong_back )
{
// if there is data ready
if ( radio.available() )
{
// Dump the payloads until we've gotten everything
unsigned long got_time;
bool done = false;
while (!done)
{
// Fetch the payload, and see if this was the last one.
done = radio.read( &got_time, sizeof(unsigned long) );
// Spew it
printf("Got payload %lu...",got_time);
// Delay just a little bit to let the other unit
// make the transition to receiver
delay(20);
}
// First, stop listening so we can talk
radio.stopListening();
// Send the final one back.
radio.write( &got_time, sizeof(unsigned long) );
printf("Sent response.\r\n");
// Now, resume listening so we catch the next packets.
radio.startListening();
}
}
}
// vim:cin:ai:sts=2 sw=2 ft=cpp
@@ -0,0 +1,123 @@
/*
// March 2014 - TMRh20 - Updated along with High Speed RF24 Library fork
// Parts derived from examples by J. Coliz <maniacbug@ymail.com>
*/
/**
* Example for efficient call-response using ack-payloads
*
* This example continues to make use of all the normal functionality of the radios including
* the auto-ack and auto-retry features, but allows ack-payloads to be written optionlly as well.
* This allows very fast call-response communication, with the responding radio never having to
* switch out of Primary Receiver mode to send back a payload, but having the option to if wanting
* to initiate communication instead of respond to a commmunication.
*/
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
// Hardware configuration: Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(7,8);
// Topology
const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate.
// Role management: Set up role. This sketch uses the same software for all the nodes
// in this system. Doing so greatly simplifies testing.
typedef enum { role_ping_out = 1, role_pong_back } role_e; // The various roles supported by this sketch
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; // The debug-friendly names of those roles
role_e role = role_pong_back; // The role of the current running sketch
// A single byte to keep track of the data being sent back and forth
byte counter = 1;
void setup(){
Serial.begin(57600);
printf_begin();
printf("\n\rRF24/examples/GettingStarted/\n\r");
printf("ROLE: %s\n\r",role_friendly_name[role]);
printf("*** PRESS 'T' to begin transmitting to the other node\n\r");
// Setup and configure rf radio
radio.begin();
radio.setAutoAck(1); // Ensure autoACK is enabled
radio.enableAckPayload(); // Allow optional ack payloads
radio.setRetries(0,15); // Smallest time between retries, max no. of retries
radio.setPayloadSize(1); // Here we are sending 1-byte payloads to test the call-response speed
radio.openWritingPipe(pipes[1]); // Both radios listen on the same pipes by default, and switch when writing
radio.openReadingPipe(1,pipes[0]);
radio.startListening(); // Start listening
radio.printDetails(); // Dump the configuration of the rf unit for debugging
}
void loop(void) {
if (role == role_ping_out){
radio.stopListening(); // First, stop listening so we can talk.
printf("Now sending %d as payload. ",counter);
byte gotByte;
unsigned long time = micros(); // Take the time, and send it. This will block until complete
//Called when STANDBY-I mode is engaged (User is finished sending)
if (!radio.write( &counter, 1 )){
printf("failed.\n\r");
}else{
if(!radio.available()){
printf("Blank Payload Received\n\r");
}else{
while(radio.available() ){
unsigned long tim = micros();
radio.read( &gotByte, 1 );
printf("Got response %d, round-trip delay: %lu microseconds\n\r",gotByte,tim-time);
counter++;
}
}
}
// Try again later
delay(1000);
}
// Pong back role. Receive each packet, dump it out, and send it back
if ( role == role_pong_back ) {
byte pipeNo;
byte gotByte; // Dump the payloads until we've gotten everything
while( radio.available(&pipeNo)){
radio.read( &gotByte, 1 );
radio.writeAckPayload(pipeNo,&gotByte, 1 );
}
}
// Change roles
if ( Serial.available() )
{
char c = toupper(Serial.read());
if ( c == 'T' && role == role_pong_back )
{
printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r");
role = role_ping_out; // Become the primary transmitter (ping out)
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1,pipes[1]);
}
else if ( c == 'R' && role == role_ping_out )
{
printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r");
role = role_pong_back; // Become the primary receiver (pong back)
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
radio.startListening();
}
}
}
@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__
@@ -0,0 +1,206 @@
PROJECT_NAME = $(PWD:B) ;
PROJECT_DIR = . ;
PROJECT_LIBS = SPI RF24 ;
OUT_DIR = ojam ;
F_CPU = 16000000 ;
MCU = atmega328p ;
PORTS = /dev/tty.usbserial-A600eHIs /dev/tty.usbserial-A40081RP /dev/tty.usbserial-A9007LmI ;
UPLOAD_RATE = 57600 ;
AVRDUDE_PROTOCOL = stk500v1 ;
COM = 33 ;
# Host-specific overrides for locations
if $(OS) = MACOSX
{
ARDUINO_VERSION = 22 ;
OLD_DIR = /opt/arduino-0021 ;
AVR_TOOLS_PATH = $(OLD_DIR)/hardware/tools/avr/bin ;
AVRDUDECONFIG_PATH = $(OLD_DIR)/hardware/tools/avr/etc ;
ARDUINO_DIR = /opt/Arduino ;
ARDUINO_AVR = /usr/lib/avr/include ;
}
# Where is everything?
ARDUINO_VERSION ?= 22 ;
AVR_TOOLS_PATH ?= /usr/bin ;
ARDUINO_DIR ?= /opt/arduino-00$(ARDUINO_VERSION) ;
ARDUINO_AVR ?= $(ARDUINO_DIR)/hardware/tools/avr/avr/include/avr ;
AVRDUDECONFIG_PATH ?= $(ARDUINO_DIR)/hardware/tools ;
ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino ;
ARDUINO_LIB = $(ARDUINO_DIR)/libraries ;
SKETCH_LIB = $(HOME)/Source/Arduino/libraries ;
AVR_CC = $(AVR_TOOLS_PATH)/avr-gcc ;
AVR_CXX = $(AVR_TOOLS_PATH)/avr-g++ ;
AVR_LD = $(AVR_TOOLS_PATH)/avr-gcc ;
AVR_OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy ;
AVRDUDE = $(AVR_TOOLS_PATH)/avrdude ;
DEFINES = F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ;
CTUNING = -ffunction-sections -fdata-sections ;
CXXTUNING = -fno-exceptions -fno-strict-aliasing ;
CFLAGS = -Os -Wall -Wextra -mmcu=$(MCU) $(CTUNING) ;
CXXFLAGS = $(CFLAGS) $(CXXTUNING) ;
LDFLAGS = -Os -lm -Wl,--gc-sections -mmcu=atmega328p ;
# Search everywhere for headers
HDRS = $(PROJECT_DIR) $(ARDUINO_AVR) $(ARDUINO_CORE) [ GLOB $(ARDUINO_LIB) $(SKETCH_LIB) : [^.]* ] ;
# Grab everything from the core directory
CORE_MODULES = [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ;
# Grab everything from libraries. To avoid this "grab everything" behaviour, you
# can specify specific modules to pick up in PROJECT_MODULES
LIB_MODULES = [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp ] ;
# In addition to explicitly-specified program modules, pick up anything from the current
# dir.
PROJECT_MODULES += [ GLOB $(PROJECT_DIR) : *.c *.cpp *.pde ] ;
# Shortcut for the out files
OUT = $(OUT_DIR)/$(PROJECT_NAME) ;
# AvrDude setup
AVRDUDE_FLAGS = -V -F -D -C $(AVRDUDECONFIG_PATH)/avrdude.conf -p $(MCU) -c $(AVRDUDE_PROTOCOL) -b $(UPLOAD_RATE) ;
rule GitVersion
{
Always $(<) ;
Depends all : $(<) ;
}
actions GitVersion
{
echo "const char program_version[] = \"\\" > $(<)
git log -1 --pretty=format:%h >> $(<)
echo "\";" >> $(<)
}
GitVersion version.h ;
rule AvrCc
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Clean clean : $(<) ;
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions AvrCc
{
$(AVR_CC) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CFLAGS) $(>)
}
rule AvrC++
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Clean clean : $(<) ;
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions AvrC++
{
$(AVR_CXX) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CXXFLAGS) $(>)
}
rule Pde
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Clean clean : $(<) ;
}
actions Pde
{
echo "#include <WProgram.h>" > $(<)
echo "#line 1 \"$(>)\"" >> $(<)
cat $(>) >> $(<)
}
rule AvrPde
{
local _CPP = $(OUT_DIR)/$(_I:B).cpp ;
Pde $(_CPP) : $(>) ;
AvrC++ $(<) : $(_CPP) ;
}
rule AvrObject
{
switch $(>:S)
{
case .c : AvrCc $(<) : $(>) ;
case .cpp : AvrC++ $(<) : $(>) ;
case .pde : AvrPde $(<) : $(>) ;
}
}
rule AvrObjects
{
for _I in $(<)
{
AvrObject $(OUT_DIR)/$(_I:B).o : $(_I) ;
}
}
rule AvrMainFromObjects
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
MkDir $(<:D) ;
Depends all : $(<) ;
Clean clean : $(<) ;
}
actions AvrMainFromObjects
{
$(AVR_LD) $(LDFLAGS) -o $(<) $(>)
}
rule AvrMain
{
AvrMainFromObjects $(<) : $(OUT_DIR)/$(>:B).o ;
AvrObjects $(>) ;
}
rule AvrHex
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Depends hex : $(<) ;
Clean clean : $(<) ;
}
actions AvrHex
{
$(AVR_OBJCOPY) -O ihex -R .eeprom $(>) $(<)
}
rule AvrUpload
{
Depends $(1) : $(2) ;
Depends $(2) : $(3) ;
NotFile $(1) ;
Always $(1) ;
Always $(2) ;
AvrUploadAction $(2) : $(3) ;
}
actions AvrUploadAction
{
$(AVRDUDE) $(AVRDUDE_FLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i
}
AvrMain $(OUT).elf : $(CORE_MODULES) $(LIB_MODULES) $(PROJECT_MODULES) ;
AvrHex $(OUT).hex : $(OUT).elf ;
AvrUpload p6 : /dev/tty.usbserial-A600eHIs : $(OUT).hex ;
AvrUpload p4 : /dev/tty.usbserial-A40081RP : $(OUT).hex ;
AvrUpload p9 : /dev/tty.usbserial-A9007LmI : $(OUT).hex ;
@@ -0,0 +1,232 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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 using Dynamic Payloads
*
* This is an example of how to use payloads of a varying (dynamic) size.
*/
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
//
// Hardware configuration
//
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(7,8);
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
// Leave open to be the 'ping' transmitter
const int role_pin = 5;
//
// Topology
//
// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
//
// 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_ping_out = 1, role_pong_back } role_e;
// The debug-friendly names of those roles
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};
// The role of the current running sketch
role_e role;
//
// Payload
//
const int min_payload_size = 4;
const int max_payload_size = 32;
const int payload_size_increments_by = 1;
int next_payload_size = min_payload_size;
char receive_payload[max_payload_size+1]; // +1 to allow room for a terminating NULL char
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_ping_out;
else
role = role_pong_back;
//
// Print preamble
//
Serial.begin(57600);
printf_begin();
printf("\n\rRF24/examples/pingpair_dyn/\n\r");
printf("ROLE: %s\n\r",role_friendly_name[role]);
//
// Setup and configure rf radio
//
radio.begin();
// enable dynamic payloads
radio.enableDynamicPayloads();
// optionally, increase the delay between retries & # of retries
radio.setRetries(5,15);
//
// Open pipes to other nodes for communication
//
// This simple sketch opens two pipes for these two nodes to communicate
// back and forth.
// Open 'our' pipe for writing
// Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)
if ( role == role_ping_out )
{
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1,pipes[1]);
}
else
{
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
}
//
// Start listening
//
radio.startListening();
//
// Dump the configuration of the rf unit for debugging
//
radio.printDetails();
}
void loop(void)
{
//
// Ping out role. Repeatedly send the current time
//
if (role == role_ping_out)
{
// The payload will always be the same, what will change is how much of it we send.
static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012";
// First, stop listening so we can talk.
radio.stopListening();
// Take the time, and send it. This will block until complete
printf("Now sending length %i...",next_payload_size);
radio.write( send_payload, next_payload_size );
// Now, continue listening
radio.startListening();
// Wait here until we get a response, or timeout
unsigned long started_waiting_at = millis();
bool timeout = false;
while ( ! radio.available() && ! timeout )
if (millis() - started_waiting_at > 500 )
timeout = true;
// Describe the results
if ( timeout )
{
printf("Failed, response timed out.\n\r");
}
else
{
// Grab the response, compare, and send to debugging spew
uint8_t len = radio.getDynamicPayloadSize();
radio.read( receive_payload, len );
// Put a zero at the end for easy printing
receive_payload[len] = 0;
// Spew it
printf("Got response size=%i value=%s\n\r",len,receive_payload);
}
// Update size for next time.
next_payload_size += payload_size_increments_by;
if ( next_payload_size > max_payload_size )
next_payload_size = min_payload_size;
// Try again 1s later
delay(100);
}
//
// Pong back role. Receive each packet, dump it out, and send it back
//
if ( role == role_pong_back )
{
// if there is data ready
if ( radio.available() )
{
// Dump the payloads until we've gotten everything
uint8_t len;
bool done = false;
while (radio.available())
{
// Fetch the payload, and see if this was the last one.
len = radio.getDynamicPayloadSize();
radio.read( receive_payload, len );
// Put a zero at the end for easy printing
receive_payload[len] = 0;
// Spew it
printf("Got payload size=%i value=%s\n\r",len,receive_payload);
}
// First, stop listening so we can talk
radio.stopListening();
// Send the final one back.
radio.write( receive_payload, len );
printf("Sent response.\n\r");
// Now, resume listening so we catch the next packets.
radio.startListening();
}
}
}
// vim:cin:ai:sts=2 sw=2 ft=cpp
@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__
@@ -0,0 +1,137 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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.
Update 2014 - TMRh20
*/
/**
* Example of using interrupts
*
* This is an example of how to user interrupts to interact with the radio, and a demonstration
* of how to use them to sleep when receiving, and not miss any payloads.
* The pingpair_sleepy example expands on sleep functionality with a timed sleep option for the transmitter.
* Sleep functionality is built directly into my fork of the RF24Network library
*/
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
#include <avr/sleep.h>
#include <avr/power.h>
// Hardware configuration
RF24 radio(7,8); // Set up nRF24L01 radio on SPI bus plus pins 9 & 10
const short role_pin = 5; // sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
// Leave open to be the 'ping' transmitter
const uint64_t address[2] = {0xABCDABCD71LL, 0x544d52687CLL}; // Radio pipe addresses for the 2 nodes to communicate.
// 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
typedef enum { role_sender = 1, role_receiver } role_e; // The various roles supported by this sketch
const char* role_friendly_name[] = { "invalid", "Sender", "Receiver"}; // The debug-friendly names of those roles
role_e role; // The role of the current running sketch
boolean gotMsg = 0; // So we know when to go to sleep
/********************** Setup *********************/
void setup(){
pinMode(role_pin, INPUT); // set up the role pin
digitalWrite(role_pin,HIGH); // Change this to LOW/HIGH instead of using an external pin
delay(20); // Just to get a solid reading on the role pin
if ( digitalRead(role_pin) ) // read the address pin, establish our role
role = role_sender;
else
role = role_receiver;
Serial.begin(115200);
printf_begin();
printf("\n\rRF24/examples/pingpair_irq/\n\r");
printf("ROLE: %s\n\r",role_friendly_name[role]);
// Setup and configure rf radio
radio.begin();
radio.enableAckPayload(); // We will be using the Ack Payload feature, so please enable it
// Open pipes to other node for communication
if ( role == role_sender ) { // This simple sketch opens a pipe on a single address for these two nodes to
radio.openWritingPipe(address[0]); // communicate back and forth. One listens on it, the other talks to it.
radio.openReadingPipe(1,address[1]);
}else{
radio.openWritingPipe(address[1]);
radio.openReadingPipe(1,address[0]);
radio.startListening();
}
radio.printDetails(); // Dump the configuration of the rf unit for debugging
delay(50);
attachInterrupt(0, check_radio, FALLING); // Attach interrupt handler to interrupt #0 (using pin 2) on BOTH the sender and receiver
}
static uint32_t message_count = 0;
/********************** Main Loop *********************/
void loop() {
if (role == role_sender) { // Sender role. Repeatedly send the current time
unsigned long time = millis(); // Take the time, and send it.
printf("Now sending %lu\n\r",time);
radio.startWrite( &time, sizeof(unsigned long) ,0);
delay(2000); // Try again soon
}
if(role == role_receiver){ // Receiver does nothing except in IRQ
}
}
/********************** Interrupt *********************/
void check_radio(void) // Receiver role: Does nothing! All the work is in IRQ
{
bool tx,fail,rx;
radio.whatHappened(tx,fail,rx); // What happened?
if ( tx ) { // Have we successfully transmitted?
if ( role == role_sender ){ printf("Send:OK\n\r"); }
if ( role == role_receiver ){ printf("Ack Payload:Sent\n\r"); }
}
if ( fail ) { // Have we failed to transmit?
if ( role == role_sender ){ printf("Send:Failed\n\r"); }
if ( role == role_receiver ){ printf("Ack Payload:Failed\n\r"); }
}
if ( rx || radio.available()){ // Did we receive a message?
if ( role == role_sender ) { // If we're the sender, we've received an ack payload
radio.read(&message_count,sizeof(message_count));
printf("Ack:%lu\n\r",message_count);
}
if ( role == role_receiver ) { // If we're the receiver, we've received a time message
static unsigned long got_time; // Get this payload and dump it
radio.read( &got_time, sizeof(got_time) );
printf("Got payload %lu\n\r",got_time);
radio.writeAckPayload( 1, &message_count, sizeof(message_count) ); // Add an ack packet for the next time around. This is a simple
++message_count; // packet counter
}
}
}
@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__
@@ -0,0 +1,225 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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.
TMRh20 2014 - Updates to the library allow sleeping both in TX and RX modes:
TX Mode: The radio can be powered down (.9uA current) and the Arduino slept using the watchdog timer
RX Mode: The radio can be left in standby mode (22uA current) and the Arduino slept using an interrupt pin
*/
/**
* Example RF Radio Ping Pair which Sleeps between Sends
*
* This is an example of how to use the RF24 class to create a battery-
* efficient system. It is just like the GettingStarted_CallResponse example, but the
* ping node powers down the radio and sleeps the MCU after every
* ping/pong cycle, and the receiver sleeps between payloads.
*
* Write this sketch to two different nodes,
* connect the role_pin to ground on one. The ping node sends the current
* time to the pong node, which responds by sending the value back. The ping
* node can then see how long the whole cycle took.
*/
#include <SPI.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(7,8);
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
// Leave open to be the 'ping' transmitter
const int role_pin = 5;
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; // Radio pipe addresses for the 2 nodes to communicate.
// 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.
// The various roles supported by this sketch
typedef enum { role_ping_out = 1, role_pong_back } role_e;
// The debug-friendly names of those roles
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};
// The role of the current running sketch
role_e role;
// Sleep declarations
typedef enum { wdt_16ms = 0, wdt_32ms, wdt_64ms, wdt_128ms, wdt_250ms, wdt_500ms, wdt_1s, wdt_2s, wdt_4s, wdt_8s } wdt_prescalar_e;
void setup_watchdog(uint8_t prescalar);
void do_sleep(void);
const short sleep_cycles_per_transmission = 4;
volatile short sleep_cycles_remaining = sleep_cycles_per_transmission;
void setup(){
// 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_ping_out;
else
role = role_pong_back;
Serial.begin(57600);
printf_begin();
printf("\n\rRF24/examples/pingpair_sleepy/\n\r");
printf("ROLE: %s\n\r",role_friendly_name[role]);
// Prepare sleep parameters
// Only the ping out role uses WDT. Wake up every 4s to send a ping
//if ( role == role_ping_out )
setup_watchdog(wdt_4s);
// Setup and configure rf radio
radio.begin();
// Open pipes to other nodes for communication
// This simple sketch opens two pipes for these two nodes to communicate
// back and forth.
// Open 'our' pipe for writing
// Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)
if ( role == role_ping_out ) {
radio.openWritingPipe(pipes[0]);
radio.openReadingPipe(1,pipes[1]);
} else {
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
}
// Start listening
radio.startListening();
// Dump the configuration of the rf unit for debugging
//radio.printDetails();
}
void loop(){
if (role == role_ping_out) { // Ping out role. Repeatedly send the current time
radio.powerUp(); // Power up the radio after sleeping
radio.stopListening(); // First, stop listening so we can talk.
unsigned long time = millis(); // Take the time, and send it.
printf("Now sending... %lu \n\r",time);
radio.write( &time, sizeof(unsigned long) );
radio.startListening(); // Now, continue listening
unsigned long started_waiting_at = millis(); // Wait here until we get a response, or timeout (250ms)
bool timeout = false;
while ( ! radio.available() ){
if (millis() - started_waiting_at > 250 ){ // Break out of the while loop if nothing available
timeout = true;
break;
}
}
if ( timeout ) { // Describe the results
printf("Failed, response timed out.\n\r");
}else{
unsigned long got_time; // Grab the response, compare, and send to debugging spew
radio.read( &got_time, sizeof(unsigned long) );
printf("Got response %lu, round-trip delay: %lu\n\r",got_time,millis()-got_time);
}
// Shut down the system
delay(500); // Experiment with some delay here to see if it has an effect
// Power down the radio.
radio.powerDown(); // NOTE: The radio MUST be powered back up again manually
// Sleep the MCU.
do_sleep();
}
// Pong back role. Receive each packet, dump it out, and send it back
if ( role == role_pong_back ) {
if ( radio.available() ) { // if there is data ready
unsigned long got_time;
while (radio.available()) { // Dump the payloads until we've gotten everything
radio.read( &got_time, sizeof(unsigned long) ); // Get the payload, and see if this was the last one.
// Spew it. Include our time, because the ping_out millis counter is unreliable
printf("Got payload %lu @ %lu...",got_time,millis()); // due to it sleeping
}
radio.stopListening(); // First, stop listening so we can talk
radio.write( &got_time, sizeof(unsigned long) ); // Send the final one back.
printf("Sent response.\n\r");
radio.startListening(); // Now, resume listening so we catch the next packets.
}else{
Serial.println("Sleeping");
delay(50); // Delay so the serial data can print out
do_sleep();
}
}
}
void wakeUp(){
sleep_disable();
}
// Sleep helpers
//Prescaler values
// 0=16ms, 1=32ms,2=64ms,3=125ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(uint8_t prescalar){
uint8_t wdtcsr = prescalar & 7;
if ( prescalar & 8 )
wdtcsr |= _BV(WDP3);
MCUSR &= ~_BV(WDRF); // Clear the WD System Reset Flag
WDTCSR = _BV(WDCE) | _BV(WDE); // Write the WD Change enable bit to enable changing the prescaler and enable system reset
WDTCSR = _BV(WDCE) | wdtcsr | _BV(WDIE); // Write the prescalar bits (how long to sleep, enable the interrupt to wake the MCU
}
ISR(WDT_vect)
{
//--sleep_cycles_remaining;
Serial.println("WDT");
}
void do_sleep(void)
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable();
attachInterrupt(0,wakeUp,LOW);
WDTCSR |= _BV(WDIE);
sleep_mode(); // System sleeps here
// The WDT_vect interrupt wakes the MCU from here
sleep_disable(); // System continues execution here when watchdog timed out
detachInterrupt(0);
WDTCSR &= ~_BV(WDIE);
}
@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__
+210
View File
@@ -0,0 +1,210 @@
# (1) Project Information
PROJECT_LIBS = SPI RF24 ;
# (2) Board Information
UPLOAD_PROTOCOL ?= stk500v1 ;
UPLOAD_SPEED ?= 57600 ;
MCU ?= atmega328p ;
F_CPU ?= 16000000 ;
CORE ?= arduino ;
VARIANT ?= standard ;
ARDUINO_VERSION ?= 100 ;
# (3) USB Ports
PORTS = p4 p6 p9 u0 u1 u2 ;
PORT_p6 = /dev/tty.usbserial-A600eHIs ;
PORT_p4 = /dev/tty.usbserial-A40081RP ;
PORT_p9 = /dev/tty.usbserial-A9007LmI ;
PORT_u0 = /dev/ttyUSB0 ;
PORT_u1 = /dev/ttyUSB1 ;
PORT_u2 = /dev/ttyUSB2 ;
# (4) Location of AVR tools
#
# This configuration assumes using avr-tools that were obtained separate from the Arduino
# distribution.
if $(OS) = MACOSX
{
AVR_BIN = /usr/local/avrtools/bin ;
AVR_ETC = /usr/local/avrtools/etc ;
AVR_INCLUDE = /usr/local/avrtools/include ;
}
else
{
AVR_BIN = /usr/bin ;
AVR_INCLUDE = /usr/lib/avr/include ;
AVR_ETC = /etc ;
}
# (5) Directories where Arduino core and libraries are located
ARDUINO_DIR ?= /opt/Arduino ;
ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/$(CORE) $(ARDUINO_DIR)/hardware/arduino/variants/$(VARIANT) ;
ARDUINO_LIB = $(ARDUINO_DIR)/libraries ;
SKETCH_LIB = $(HOME)/Source/Arduino/libraries ;
#
# --------------------------------------------------
# Below this line usually never needs to be modified
#
# Tool locations
CC = $(AVR_BIN)/avr-gcc ;
C++ = $(AVR_BIN)/avr-g++ ;
LINK = $(AVR_BIN)/avr-gcc ;
OBJCOPY = $(AVR_BIN)/avr-objcopy ;
AVRDUDE = $(AVR_BIN)/avrdude ;
# Flags
DEFINES += F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ;
OPTIM = -Os ;
CCFLAGS = -Wall -Wextra -mmcu=$(MCU) -ffunction-sections -fdata-sections ;
C++FLAGS = $(CCFLAGS) -fno-exceptions -fno-strict-aliasing ;
LINKFLAGS = $(OPTIM) -lm -Wl,--gc-sections -mmcu=$(MCU) ;
AVRDUDEFLAGS = -V -F -D -C $(AVR_ETC)/avrdude.conf -p $(MCU) -c $(UPLOAD_PROTOCOL) -b $(UPLOAD_SPEED) ;
# Search everywhere for headers
HDRS = $(PWD) $(AVR_INCLUDE) $(ARDUINO_CORE) $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) ;
# Output locations
LOCATE_TARGET = $(F_CPU) ;
LOCATE_SOURCE = $(F_CPU) ;
#
# Custom rules
#
rule GitVersion
{
Always $(<) ;
Depends all : $(<) ;
}
actions GitVersion
{
echo "const char program_version[] = \"\\" > $(<)
git log -1 --pretty=format:%h >> $(<)
echo "\";" >> $(<)
}
GitVersion version.h ;
rule Pde
{
Depends $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_SOURCE) ;
Clean clean : $(<) ;
}
if ( $(ARDUINO_VERSION) < 100 )
{
ARDUINO_H = WProgram.h ;
}
else
{
ARDUINO_H = Arduino.h ;
}
actions Pde
{
echo "#include <$(ARDUINO_H)>" > $(<)
echo "#line 1 \"$(>)\"" >> $(<)
cat $(>) >> $(<)
}
rule C++Pde
{
local _CPP = $(>:B).cpp ;
Pde $(_CPP) : $(>) ;
C++ $(<) : $(_CPP) ;
}
rule UserObject
{
switch $(>:S)
{
case .ino : C++Pde $(<) : $(>) ;
case .pde : C++Pde $(<) : $(>) ;
}
}
rule Objects
{
local _i ;
for _i in [ FGristFiles $(<) ]
{
local _b = $(_i:B)$(SUFOBJ) ;
local _o = $(_b:G=$(SOURCE_GRIST:E)) ;
Object $(_o) : $(_i) ;
Depends obj : $(_o) ;
}
}
rule Main
{
MainFromObjects $(<) : $(>:B)$(SUFOBJ) ;
Objects $(>) ;
}
rule Hex
{
Depends $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_TARGET) ;
Depends hex : $(<) ;
Clean clean : $(<) ;
}
actions Hex
{
$(OBJCOPY) -O ihex -R .eeprom $(>) $(<)
}
rule Upload
{
Depends $(1) : $(2) ;
Depends $(2) : $(3) ;
NotFile $(1) ;
Always $(1) ;
Always $(2) ;
UploadAction $(2) : $(3) ;
}
actions UploadAction
{
$(AVRDUDE) $(AVRDUDEFLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i
}
#
# Targets
#
# Grab everything from the core directory
CORE_MODULES = [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ;
# Grab everything from libraries. To avoid this "grab everything" behaviour, you
# can specify specific modules to pick up in PROJECT_MODULES
LIB_MODULES = [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp *.c ] ;
# Grab everything from the current dir
PROJECT_MODULES += [ GLOB $(PWD) : *.c *.cpp *.pde *.ino ] ;
# Main output executable
MAIN = $(PWD:B).elf ;
Main $(MAIN) : $(CORE_MODULES) $(LIB_MODULES) $(PROJECT_MODULES) ;
Hex $(MAIN:B).hex : $(MAIN) ;
# Upload targets
for _p in $(PORTS)
{
Upload $(_p) : $(PORT_$(_p)) : $(MAIN:B).hex ;
}
Binary file not shown.
@@ -0,0 +1,128 @@
#include <WProgram.h>
#line 1 "scanner.pde"
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
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.
*/
/**
* Channel scanner
*
* Example to detect interference on the various channels available.
* This is a good diagnostic tool to check whether you're picking a
* good channel for your application.
*
* Inspired by cpixip.
* See http://arduino.cc/forum/index.php/topic,54795.0.html
*/
#include <SPI.h>
#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);
//
// Channel info
//
const short num_channels = 128;
short values[num_channels];
//
// Setup
//
void setup(void)
{
//
// Print preamble
//
Serial.begin(57600);
printf_begin();
printf("\n\rRF24/examples/scanner/\n\r");
//
// Setup and configure rf radio
//
radio.begin();
radio.setAutoAck(false);
// Get into standby mode
radio.startListening();
radio.stopListening();
// Print out header, high then low digit
int i = 0;
while ( i < num_channels )
{
printf("%x",i>>4);
++i;
}
printf("\n\r");
i = 0;
while ( i < num_channels )
{
printf("%x",i&0xf);
++i;
}
printf("\n\r");
}
//
// Loop
//
const short num_reps = 100;
void loop(void)
{
// Clear measurement values
memset(values,0,num_channels);
// Scan all channels num_reps times
int rep_counter = num_reps;
while (rep_counter--)
{
int i = num_channels;
while (i--)
{
// Select this channel
radio.setChannel(i);
// Listen for a little
radio.startListening();
delayMicroseconds(128);
radio.stopListening();
// Did we get a carrier?
if ( radio.testCarrier() )
++values[i];
}
}
// Print out channel measurements, clamped to a single hex digit
int i = 0;
while ( i < num_channels )
{
printf("%x",min(0xf,values[i]&0xf));
++i;
}
printf("\n\r");
}
// vim:ai:cin:sts=2 sw=2 ft=cpp
Binary file not shown.
@@ -0,0 +1,325 @@
:100000000C9463000C948B000C948B000C948B006C
:100010000C948B000C948B000C948B000C948B0034
:100020000C948B000C948B000C948B000C948B0024
:100030000C948B000C948B000C948B000C948B0014
:100040000C948F050C948B000C9423060C948B005D
:100050000C948B000C948B000C948B000C948B00F4
:100060000C948B000C948B000000000024002700EF
:100070002A0000000000250028002B0000000000DE
:1000800023002600290004040404040404040202DA
:100090000202020203030303030301020408102007
:1000A0004080010204081020010204081020000012
:1000B0000007000201000003040600000000000029
:1000C000000090043B0711241FBECFEFD8E0DEBF35
:1000D000CDBF11E0A0E0B1E0E6EFF3E102C0059092
:1000E0000D92AA33B107D9F712E0AAE3B1E001C03B
:1000F0001D92A13FB107E1F710E0C6ECD0E004C0CB
:100100002297FE010E94F509C23CD107C9F70E945F
:100110001C060C94F9090C9400000F931F93CF93C5
:10012000DF938C01EB01009731F46115710519F42F
:1001300020E030E038C081E090E06EE070E00E94A6
:10014000CB02FC019C01009771F180E8838320972A
:1001500071F0D387C28781E883838091E702909111
:10016000E802892B21F4F093E802E093E7020115FD
:100170001105C9F011870087838182608383809194
:10018000E9029091EA02892B71F4F093EA02E0937C
:10019000E9028091EB029091EC02892B21F4F0931B
:1001A000EC02E093EB02C901DF91CF911F910F9117
:1001B0000895A0E0B0E0EFEDF0E00C94CC09FE0172
:1001C0003596619171918091E9029091EA02AF01B7
:1001D0000E94EE002096E2E00C94E809ABE0B0E06B
:1001E000E4EFF0E00C94BC093C012B015A01FC0146
:1001F00017821682838181FD03C06FEF7FEFC6C136
:100200009AE0892E1E010894211C311CF3012381E0
:10021000F20123FD859123FF81912F01882309F4A9
:10022000B2C1853239F423FD859123FF81912F01DD
:10023000853229F490E0B3010E940604E7CF982F9D
:10024000FF24EE249924FFE1FF15D0F09B3269F0E2
:100250009C3228F4903259F0933291F40EC09D32C2
:1002600049F0903369F441E024C052E0F52A84E07B
:10027000F82A28C098E0F92A25C0E0E1FE2A22C029
:10028000F7FC29C0892F80538A3070F4F6FE05C030
:10029000989C902C1124980E15C0E89CE02C1124F9
:1002A000E80EF0E2FF2A0EC09E3229F4F6FC6BC184
:1002B00040E4F42A07C09C3619F450E8F52A02C03D
:1002C000983649F4F20123FD959123FF91912F0176
:1002D000992309F0B8CF892F8554833018F08052C4
:1002E000833038F444E050E0A40EB51E5FE3598338
:1002F0000FC0933631F0933779F0933509F056C03B
:1003000020C0F5018081898342E050E0A40EB51E33
:10031000610101E010E012C0F501C080D180F6FC5F
:1003200003C06FEF7FEF02C0692D70E042E050E044
:10033000A40EB51EC6010E94FB038C015FE7F522E7
:1003400014C0F501C080D180F6FC03C06FEF7FEFD1
:1003500002C0692D70E042E050E0A40EB51EC60157
:100360000E94E9038C0150E8F52AF3FE07C01AC089
:1003700080E290E0B3010E940604EA948E2D90E0A2
:1003800008171907A8F30EC0F601F7FC8591F7FED0
:1003900081916F0190E0B3010E940604E110EA949C
:1003A000015010400115110579F7EAC0943611F09B
:1003B000993669F5F7FE08C0F50120813181428147
:1003C000538184E090E00AC0F501808191819C0115
:1003D000442737FD4095542F82E090E0A80EB91EC7
:1003E0009FE6F92257FF09C0509540953095219519
:1003F0003F4F4F4F5F4FE0E8FE2ACA01B901A1010C
:100400002AE030E00E943204D82ED21840C095373E
:1004100029F41F2D1F7E2AE030E01DC01F2D197FFB
:100420009F3661F0903720F4983509F0ACC00FC0CA
:10043000903739F0983709F0A6C004C028E030E0C2
:100440000AC0106114FD146020E130E004C014FD06
:10045000166020E132E017FF08C0F501608171816C
:100460008281938144E050E008C0F5018081918150
:10047000BC0180E090E042E050E0A40EB51EA10176
:100480000E943204D82ED2188FE7F82EF122F6FE01
:100490000BC05EEFF522D91438F4F4FE07C0F2FC6D
:1004A00005C08FEEF82202C01D2D01C0192DF4FEEB
:1004B0000DC0FE01ED0DF11D8081803319F499EE20
:1004C000F92208C01F5FF2FE05C003C08F2D867899
:1004D00009F01F5F0F2DF3FC14C0F0FE0FC01E15B6
:1004E00010F09D2C0BC09D2C9E0C911A1E2D06C049
:1004F00080E290E0B3010E9406041F5F1E15C0F366
:1005000004C01E1510F4E11A01C0EE2404FF0FC050
:1005100080E390E0B3010E94060402FF1DC001FDCC
:1005200003C088E790E00EC088E590E00BC0802F04
:10053000867891F001FF02C08BE201C080E2F7FCF7
:100540008DE290E0B3010E94060406C080E390E0D3
:10055000B3010E9406049A94D914C0F3DA94F1010D
:10056000ED0DF11D808190E0B3010E940604DD20B5
:10057000A9F706C080E290E0B3010E940604EA9465
:10058000EE20C1F743CEF30166817781CB012B9634
:10059000E2E10C94D8090F931F93CF93DF93689FE8
:1005A0008001699F100D789F100D1124C8010E94D1
:1005B000E702EC01009729F060E070E0A8010E94DA
:1005C000F403CE01DF91CF911F910F910895CF9346
:1005D000DF93BC018230910510F462E070E0A091DD
:1005E000EF02B091F002ED01E0E0F0E040E050E019
:1005F00021C0888199818617970769F48A819B8138
:10060000309719F09383828304C09093F002809313
:10061000EF02FE0134C06817790738F4411551051F
:1006200019F08417950708F4AC01FE018A819B81BB
:100630009C01E9012097E9F641155105A9F1CA018C
:10064000861B970B049708F4BA01E0E0F0E02AC09B
:100650008D919C91119784179507F9F4641775078C
:1006600081F412968D919C911397309719F0938392
:10067000828304C09093F0028093EF02FD013296D2
:100680004CC0CA01861B970BFD01E80FF91F61934F
:10069000719302978D939C9340C0FD018281938159
:1006A0009C01D9011097A1F68091ED029091EE0284
:1006B000892B41F480912301909124019093EE02C3
:1006C0008093ED024091250150912601411551057D
:1006D00041F44DB75EB78091210190912201481BF2
:1006E000590B2091ED023091EE02CA01821B930B4F
:1006F0008617970780F0AB014E5F5F4F8417950711
:1007000050F0420F531F5093EE024093ED02F90157
:100710006193719302C0E0E0F0E0CF01DF91CF91EF
:100720000895CF93DF93009709F450C0EC0122970E
:100730001B821A82A091EF02B091F002109709F18A
:1007400040E050E0AC17BD0708F1BB83AA83FE016F
:1007500021913191E20FF31FAE17BF0779F48D910C
:100760009C911197280F391F2E5F3F4F39832883A3
:1007700012968D919C9113979B838A834115510505
:1007800071F4D093F002C093EF0220C012968D91C5
:100790009C911397AD01009711F0DC01D3CFFA01C2
:1007A000D383C28321913191E20FF31FCE17DF076C
:1007B00069F488819981280F391F2E5F3F4FFA0114
:1007C000318320838A819B8193838283DF91CF91C0
:1007D0000895FC010590615070400110D8F7809594
:1007E00090958E0F9F1F0895DC0101C06D934150BD
:1007F0005040E0F70895FC016150704001900110F5
:10080000D8F7809590958E0F9F1F08950F931F9393
:10081000CF93DF938C01EB018B8181FF1BC082FFA3
:100820000DC02E813F818C819D812817390764F48A
:10083000E881F9810193F983E88306C0E885F985A9
:10084000802F0995892B31F48E819F8101969F839A
:100850008E8302C00FEF1FEFC801DF91CF911F9170
:100860000F910895FA01AA27283051F1203181F122
:10087000E8946F936E7F6E5F7F4F8F4F9F4FAF4FA8
:10088000B1E03ED0B4E03CD0670F781F891F9A1FBB
:10089000A11D680F791F8A1F911DA11D6A0F711D6F
:1008A000811D911DA11D20D009F468943F912AE07B
:1008B000269F11243019305D3193DEF6CF01089563
:1008C000462F4770405D4193B3E00FD0C9F7F6CF94
:1008D000462F4F70405D4A3318F0495D31FD40525C
:1008E000419302D0A9F7EACFB4E0A69597958795F2
:1008F00077956795BA95C9F70097610571050895D1
:100900009B01AC010A2E069457954795379527957C
:10091000BA95C9F7620F731F841F951FA01D089514
:100920008AE391E068E049E00E9475070895FF922C
:100930000F931F93CF93DF9380E8E7E4F1E0DF01AB
:100940001D928A95E9F704E610E021C08AE391E060
:100950006F2D0E94F2078AE391E00E94840880E8EC
:1009600090E00E94D7058AE391E00E947C078AE329
:1009700091E00E944608882329F088819981019698
:10098000998388832297FA94BFEFFB16F9F60150FA
:100990001040EFEF0F3F1E0729F0C5E4D2E08FE7CC
:1009A000F82ED4CFC7E4D1E000E011E000D000D0B1
:1009B000ADB7BEB712961C930E931197899199917A
:1009C0008F70907014969C938E9313970E94D90009
:1009D0000F900F900F900F90B2E0C734DB0731F704
:1009E00000D083E091E0EDB7FEB7928381830E944F
:1009F000D9000F900F90DF91CF911F910F91FF9031
:100A0000089580E895E060E070E00E948D00089510
:100A10000F931F93CF93DF9384ED92E040E051EE6C
:100A200060E070E00E9454060E94010500D086E05C
:100A300091E0EDB7FEB7928381830E94D9000F90B9
:100A40000F908AE391E00E944B088AE391E060E016
:100A50000E94E8078AE391E00E9484088AE391E01B
:100A60000E947C07C0E0D0E000E011E000D000D0A0
:100A7000EDB7FEB712830183CE0124E095958795EB
:100A80002A95E1F7948383830E94D90021960F90E1
:100A90000F900F900F90C038D10541F700D083E040
:100AA00091E0EDB7FEB7928381830E94D900C0E048
:100AB000D0E00F900F9000D000D0EDB7FEB70183CB
:100AC0001283CE018F709070948383830E94D9002B
:100AD00021960F900F900F900F90C038D10559F7C5
:100AE00000D083E091E0EDB7FEB7928381830E944E
:100AF000D9000F900F90DF91CF911F910F91089522
:100B00000F931F93082F84ED92E0602F0E94280717
:100B1000112707FD1095C8011F910F9108951F928D
:100B20000F920FB60F9211242F933F938F939F93A1
:100B3000AF93BF9380914B0290914C02A0914D02D4
:100B4000B0914E0230914F020196A11DB11D232F8D
:100B50002D5F2D3720F02D570196A11DB11D20933B
:100B60004F0280934B0290934C02A0934D02B0939E
:100B70004E028091470290914802A0914902B091A3
:100B80004A020196A11DB11D80934702909348022D
:100B9000A0934902B0934A02BF91AF919F918F9168
:100BA0003F912F910F900FBE0F901F9018950197B6
:100BB00039F0880F991F880F991F02970197F1F755
:100BC0000895789484B5826084BD84B5816084BDC5
:100BD00085B5826085BD85B5816085BDEEE6F0E0B6
:100BE000808181608083E1E8F0E010828081826012
:100BF0008083808181608083E0E8F0E08081816093
:100C00008083E1EBF0E0808184608083E0EBF0E0C2
:100C1000808181608083EAE7F0E080818460808366
:100C20008081826080838081816080838081806810
:100C300080831092C10008950E94E1050E9408057A
:100C40000E949704FDCF1F920F920FB60F921124AE
:100C50002F933F934F938F939F93EF93FF934091E5
:100C6000C600E091D002F091D10231969F012F771A
:100C7000307031978091D2029091D30228173907B2
:100C800039F0E05BFD4F40833093D1022093D002D6
:100C9000FF91EF919F918F914F913F912F910F90E5
:100CA0000FBE0F901F901895AF92BF92DF92EF92F8
:100CB000FF920F931F93CF93DF93EC017A018B0187
:100CC000DD24403081EE580780E0680780E0780737
:100CD00011F0DD24D39491E0A92EB12CE885F9859B
:100CE000DD2069F0C5010A8802C0880F991F0A94A7
:100CF000E2F7808360E079E08DE390E005C0108248
:100D000060E874E88EE190E0A80197010E949A09DA
:100D10002150304040405040569547953795279593
:100D200080E12030380720F0DD2011F0DD24D6CF1F
:100D3000EC81FD813083EE81FF812083EA85FB8594
:100D4000208141E050E0CA010E8402C0880F991F43
:100D50000A94E2F7282B2083EA85FB852081CA01CB
:100D60000F8402C0880F991F0A94E2F7282B208372
:100D7000EA85FB858081088802C0440F551F0A94CC
:100D8000E2F7842B8083DF91CF911F910F91FF9029
:100D9000EF90DF90BF90AF900895DC011296ED9137
:100DA000FC911397E058FF4F2191319180819181FF
:100DB000281B390B2F773070C9010895DC0112967A
:100DC000ED91FC911397EE57FF4F20813181929165
:100DD0008291E058F0408217930719F42FEF3FEF0C
:100DE00005C0E20FF31F8081282F30E0C90108956C
:100DF000DC011296ED91FC911397DF01AE57BF4FC6
:100E00002D913C911197E058FF4F80819181E058DE
:100E1000F0408217930719F42FEF3FEF0BC0E20F5A
:100E2000F31F80812F5F3F4F2F7730702D933C93BE
:100E3000282F30E0C9010895DC011296ED91FC9154
:100E40001397EE57FF4F808191819293829308957B
:100E5000FC01A085B18521898C9190E0022E02C011
:100E6000959587950A94E2F780FFF6CF0484F5857F
:100E7000E02D608308958BE291E09093D5028093FA
:100E8000D40280E592E09093D7028093D60285EC5D
:100E900090E09093D9028093D80284EC90E09093F4
:100EA000DB028093DA0280EC90E09093DD02809385
:100EB000DC0281EC90E09093DF028093DE0286EC0E
:100EC00090E09093E1028093E00284E08093E2025C
:100ED00083E08093E30287E08093E40285E08093DF
:100EE000E50281E08093E6020895FC01608341837E
:100EF00080E2828313820895FC01808160E00E9479
:100F0000CD080895FF920F931F938C01F62E80E079
:100F10000E94650985E00E946A09F80181816F2DB0
:100F20000E94CD081F910F91FF9008951F93CF93BA
:100F3000DF93EC0160E070E00E94820781EE8EBDDD
:100F40000DB407FEFDCF1EB5CE0161E070E00E943A
:100F50008207812FDF91CF911F9108951F93CF9327
:100F6000DF93EC0160E070E00E94820782EE8EBDAC
:100F70000DB407FEFDCF1EB5CE0161E070E00E940A
:100F80008207812FDF91CF911F9108950F931F93B7
:100F9000CF93DF93EC01162F042F60E070E00E94E6
:100FA00082071F7110621EBD0DB407FEFDCF1EB576
:100FB0000EBD0DB407FEFDCF8EB5CE0161E070E031
:100FC0000E948207812FDF91CF911F910F91089589
:100FD000662319F061E04FE302C061E040E00E9447
:100FE000C6070895462F603808F04FE765E00E9475
:100FF000C6070895EF92FF920F931F93CF93DF934D
:101000007C01162FEA01022F60E070E00E94820747
:101010001F7110621EBD0DB407FEFDCF1EB508C0C6
:1010200088818EBD0DB407FEFDCF21968EB501508F
:101030000023B1F7C70161E070E00E948207812FB1
:10104000DF91CF911F910F91FF90EF9008951F9323
:10105000CF93DF93EC01162F60E070E00E948207CF
:101060001F711EBD0DB407FEFDCF8EB58FEF8EBD77
:101070000DB407FEFDCF1EB5CE0161E070E00E9409
:101080008207812FDF91CF911F91089569E00E941F
:101090002708817008950F931F938C01FC018081B4
:1010A00061E00E94A708F801818161E00E94A70821
:1010B000F801808160E00E94CD08C80161E070E025
:1010C0000E9482070E947B0981E00E945C0980E007
:1010D0000E94650985E00E946A09C80164E04FEF3B
:1010E0000E94C607C80167E040E70E94C607C80122
:1010F0000E94AE07C8010E949607C80161E00E94E5
:10110000F2071F910F9108950F931F938C0160E0D8
:101110004BE00E94C607C80167E040E70E94C6078F
:10112000A8014B5F5F4FC8016AE025E00E94FA0703
:10113000C8010E94AE07F801808161E00E94CD08DD
:1011400082E890E00E94D7051F910F910895482FE3
:1011500050E0CA0186569F4FFC0124914A575F4FC9
:10116000FA0184918823C1F0E82FF0E0EE0FFF1F11
:10117000E859FF4FA591B491662341F49FB7F894C5
:101180008C91209582238C939FBF08959FB7F894EC
:101190008C91822B8C939FBF0895482F50E0CA01F9
:1011A00082559F4FFC012491CA0186569F4FFC0136
:1011B00034914A575F4FFA019491992309F444C03E
:1011C000222351F1233071F0243028F42130A1F092
:1011D000223011F514C02630B1F02730C1F0243090
:1011E000D9F404C0809180008F7703C08091800083
:1011F0008F7D8093800010C084B58F7702C084B546
:101200008F7D84BD09C08091B0008F7703C080912D
:10121000B0008F7D8093B000E92FF0E0EE0FFF1F4C
:10122000EE58FF4FA591B491662341F49FB7F8940F
:101230008C91309583238C939FBF08959FB7F8942A
:101240008C91832B8C939FBF08950F931F93CF9303
:10125000DF938C01EB0109C02196D801ED91FC913F
:101260000190F081E02DC801099568816623A1F7FE
:10127000DF91CF911F910F910895EF92FF920F93FD
:101280001F93CF93DF938C017B01EA010CC0D70140
:101290006D917D01D801ED91FC910190F081E02DDF
:1012A000C80109952197209791F7DF91CF911F9160
:1012B0000F91FF90EF900895882319F48CB5806208
:1012C00002C08CB58F7D8CBD08959CB5937F982B03
:1012D0009CBD08952CB5382F33702C7F322B3CBD2C
:1012E0002DB590E0959587959595879581702E7F82
:1012F000822B8DBD08958DE061E00E94A7088BE0F0
:1013000061E00E94A7088AE061E00E94A7088DE0E2
:1013100060E00E94CD088BE060E00E94CD088AE08A
:1013200061E00E94CD088CB580618CBD8CB5806475
:101330008CBD0895A1E21A2EAA1BBB1BFD010DC096
:10134000AA1FBB1FEE1FFF1FA217B307E407F50775
:1013500020F0A21BB30BE40BF50B661F771F881F51
:10136000991F1A9469F760957095809590959B01E7
:10137000AC01BD01CF0108952F923F924F925F9231
:101380006F927F928F929F92AF92BF92CF92DF9295
:10139000EF92FF920F931F93CF93DF93CDB7DEB7FA
:1013A000CA1BDB0B0FB6F894DEBF0FBECDBF09948E
:1013B0002A88398848885F846E847D848C849B84E5
:1013C000AA84B984C884DF80EE80FD800C811B81F3
:1013D000AA81B981CE0FD11D0FB6F894DEBF0FBE22
:1013E000CDBFED010895EE0FFF1F0590F491E02DA4
:0613F0000994F894FFCF00
:1013F6002578000A0D000A0D524632342F657861B1
:101406006D706C65732F7363616E6E65722F0A0D56
:10141600002000F102000000000000280725093D19
:0A14260009CD06F806DE061C0700DB
:00000001FF
+31
View File
@@ -0,0 +1,31 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#endif // __PRINTF_H__
+126
View File
@@ -0,0 +1,126 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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.
*/
/**
* Channel scanner
*
* Example to detect interference on the various channels available.
* This is a good diagnostic tool to check whether you're picking a
* good channel for your application.
*
* Inspired by cpixip.
* See http://arduino.cc/forum/index.php/topic,54795.0.html
*/
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
//
// Hardware configuration
//
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
//
// Channel info
//
const uint8_t num_channels = 128;
uint8_t values[num_channels];
//
// Setup
//
void setup(void)
{
//
// Print preamble
//
Serial.begin(57600);
printf_begin();
printf("\n\rRF24/examples/scanner/\n\r");
//
// Setup and configure rf radio
//
radio.begin();
radio.setAutoAck(false);
// Get into standby mode
radio.startListening();
radio.stopListening();
// Print out header, high then low digit
int i = 0;
while ( i < num_channels )
{
printf("%x",i>>4);
++i;
}
printf("\n\r");
i = 0;
while ( i < num_channels )
{
printf("%x",i&0xf);
++i;
}
printf("\n\r");
}
//
// Loop
//
const int num_reps = 100;
void loop(void)
{
// Clear measurement values
memset(values,0,sizeof(values));
// Scan all channels num_reps times
int rep_counter = num_reps;
while (rep_counter--)
{
int i = num_channels;
while (i--)
{
// Select this channel
radio.setChannel(i);
// Listen for a little
radio.startListening();
delayMicroseconds(225);
// Did we get a carrier?
if ( radio.testCarrier() ){
++values[i];
}
radio.stopListening();
}
}
// Print out channel measurements, clamped to a single hex digit
int i = 0;
while ( i < num_channels )
{
printf("%x",min(0xf,values[i]&0xf));
++i;
}
printf("\n\r");
}
// vim:ai:cin:sts=2 sw=2 ft=cpp
+206
View File
@@ -0,0 +1,206 @@
PROJECT_NAME = $(PWD:B) ;
PROJECT_DIR = . ;
PROJECT_LIBS = EEPROM SPI RF24 ;
OUT_DIR = ojam ;
F_CPU = 16000000 ;
MCU = atmega328p ;
PORTS = /dev/tty.usbserial-A600eHIs /dev/tty.usbserial-A40081RP /dev/tty.usbserial-A9007LmI ;
UPLOAD_RATE = 57600 ;
AVRDUDE_PROTOCOL = stk500v1 ;
COM = 33 ;
# Host-specific overrides for locations
if $(OS) = MACOSX
{
ARDUINO_VERSION = 22 ;
OLD_DIR = /opt/arduino-0021 ;
AVR_TOOLS_PATH = $(OLD_DIR)/hardware/tools/avr/bin ;
AVRDUDECONFIG_PATH = $(OLD_DIR)/hardware/tools/avr/etc ;
ARDUINO_DIR = /opt/Arduino ;
ARDUINO_AVR = /usr/lib/avr/include ;
}
# Where is everything?
ARDUINO_VERSION ?= 22 ;
AVR_TOOLS_PATH ?= /usr/bin ;
ARDUINO_DIR ?= /opt/arduino-00$(ARDUINO_VERSION) ;
ARDUINO_AVR ?= $(ARDUINO_DIR)/hardware/tools/avr/avr/include/avr ;
AVRDUDECONFIG_PATH ?= $(ARDUINO_DIR)/hardware/tools ;
ARDUINO_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino ;
ARDUINO_LIB = $(ARDUINO_DIR)/libraries ;
SKETCH_LIB = $(HOME)/Source/Arduino/libraries ;
AVR_CC = $(AVR_TOOLS_PATH)/avr-gcc ;
AVR_CXX = $(AVR_TOOLS_PATH)/avr-g++ ;
AVR_LD = $(AVR_TOOLS_PATH)/avr-gcc ;
AVR_OBJCOPY = $(AVR_TOOLS_PATH)/avr-objcopy ;
AVRDUDE = $(AVR_TOOLS_PATH)/avrdude ;
DEFINES = F_CPU=$(F_CPU)L ARDUINO=$(ARDUINO_VERSION) VERSION_H ;
CTUNING = -ffunction-sections -fdata-sections ;
CXXTUNING = -fno-exceptions -fno-strict-aliasing ;
CFLAGS = -Os -Wall -Wextra -mmcu=$(MCU) $(CTUNING) ;
CXXFLAGS = $(CFLAGS) $(CXXTUNING) ;
LDFLAGS = -Os -lm -Wl,--gc-sections -mmcu=atmega328p ;
# Search everywhere for headers
HDRS = $(PROJECT_DIR) $(ARDUINO_AVR) $(ARDUINO_CORE) [ GLOB $(ARDUINO_LIB) $(SKETCH_LIB) : [^.]* ] ;
# Grab everything from the core directory
CORE_MODULES = [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ;
# Grab everything from libraries. To avoid this "grab everything" behaviour, you
# can specify specific modules to pick up in PROJECT_MODULES
LIB_MODULES = [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp ] ;
# In addition to explicitly-specified program modules, pick up anything from the current
# dir.
PROJECT_MODULES += [ GLOB $(PROJECT_DIR) : *.c *.cpp *.pde ] ;
# Shortcut for the out files
OUT = $(OUT_DIR)/$(PROJECT_NAME) ;
# AvrDude setup
AVRDUDE_FLAGS = -V -F -D -C $(AVRDUDECONFIG_PATH)/avrdude.conf -p $(MCU) -c $(AVRDUDE_PROTOCOL) -b $(UPLOAD_RATE) ;
rule GitVersion
{
Always $(<) ;
Depends all : $(<) ;
}
actions GitVersion
{
echo "const char program_version[] = \"\\" > $(<)
git log -1 --pretty=format:%h >> $(<)
echo "\";" >> $(<)
}
GitVersion version.h ;
rule AvrCc
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Clean clean : $(<) ;
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions AvrCc
{
$(AVR_CC) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CFLAGS) $(>)
}
rule AvrC++
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Clean clean : $(<) ;
CCHDRS on $(<) = [ on $(<) FIncludes $(HDRS) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions AvrC++
{
$(AVR_CXX) -c -o $(<) $(CCHDRS) $(CCDEFS) $(CXXFLAGS) $(>)
}
rule Pde
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Clean clean : $(<) ;
}
actions Pde
{
echo "#include <WProgram.h>" > $(<)
echo "#line 1 \"$(>)\"" >> $(<)
cat $(>) >> $(<)
}
rule AvrPde
{
local _CPP = $(OUT_DIR)/$(_I:B).cpp ;
Pde $(_CPP) : $(>) ;
AvrC++ $(<) : $(_CPP) ;
}
rule AvrObject
{
switch $(>:S)
{
case .c : AvrCc $(<) : $(>) ;
case .cpp : AvrC++ $(<) : $(>) ;
case .pde : AvrPde $(<) : $(>) ;
}
}
rule AvrObjects
{
for _I in $(<)
{
AvrObject $(OUT_DIR)/$(_I:B).o : $(_I) ;
}
}
rule AvrMainFromObjects
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
MkDir $(<:D) ;
Depends all : $(<) ;
Clean clean : $(<) ;
}
actions AvrMainFromObjects
{
$(AVR_LD) $(LDFLAGS) -o $(<) $(>)
}
rule AvrMain
{
AvrMainFromObjects $(<) : $(OUT_DIR)/$(>:B).o ;
AvrObjects $(>) ;
}
rule AvrHex
{
Depends $(<) : $(>) ;
Depends $(<) : $(<:D) ;
Depends hex : $(<) ;
Clean clean : $(<) ;
}
actions AvrHex
{
$(AVR_OBJCOPY) -O ihex -R .eeprom $(>) $(<)
}
rule AvrUpload
{
Depends $(1) : $(2) ;
Depends $(2) : $(3) ;
NotFile $(1) ;
Always $(1) ;
Always $(2) ;
AvrUploadAction $(2) : $(3) ;
}
actions AvrUploadAction
{
$(AVRDUDE) $(AVRDUDE_FLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i
}
AvrMain $(OUT).elf : $(CORE_MODULES) $(LIB_MODULES) $(PROJECT_MODULES) ;
AvrHex $(OUT).hex : $(OUT).elf ;
AvrUpload p6 : /dev/tty.usbserial-A600eHIs : $(OUT).hex ;
AvrUpload p4 : /dev/tty.usbserial-A40081RP : $(OUT).hex ;
AvrUpload p9 : /dev/tty.usbserial-A9007LmI : $(OUT).hex ;
+37
View File
@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__
@@ -0,0 +1,293 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
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 RF Radio Ping Star Group
*
* This sketch is a more complex example of using the RF24 library for Arduino.
* Deploy this on up to six nodes. Set one as the 'pong receiver' by tying the
* role_pin low, and the others will be 'ping transmit' units. The ping units
* unit will send out the value of millis() once a second. The pong unit will
* respond back with a copy of the value. Each ping unit can get that response
* back, and determine how long the whole cycle took.
*
* This example requires a bit more complexity to determine which unit is which.
* The pong receiver is identified by having its role_pin tied to ground.
* The ping senders are further differentiated by a byte in eeprom.
*/
#include <SPI.h>
#include <EEPROM.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"
//
// Hardware configuration
//
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
// Leave open to be the 'pong' receiver.
const int role_pin = 7;
//
// Topology
//
// Radio pipe addresses for the nodes to communicate. Only ping nodes need
// dedicated pipes in this topology. Each ping node has a talking pipe
// that it will ping into, and a listening pipe that it will listen for
// the pong. The pong node listens on all the ping node talking pipes
// and sends the pong back on the sending node's specific listening pipe.
const uint64_t talking_pipes[5] = { 0xF0F0F0F0D2LL, 0xF0F0F0F0C3LL, 0xF0F0F0F0B4LL, 0xF0F0F0F0A5LL, 0xF0F0F0F096LL };
const uint64_t listening_pipes[5] = { 0x3A3A3A3AD2LL, 0x3A3A3A3AC3LL, 0x3A3A3A3AB4LL, 0x3A3A3A3AA5LL, 0x3A3A3A3A96LL };
//
// 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_invalid = 0, role_ping_out, role_pong_back } role_e;
// The debug-friendly names of those roles
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};
// The role of the current running sketch
role_e role;
//
// Address management
//
// Where in EEPROM is the address stored?
const uint8_t address_at_eeprom_location = 0;
// What is our address (SRAM cache of the address from EEPROM)
// Note that zero is an INVALID address. The pong back unit takes address
// 1, and the rest are 2-6
uint8_t node_address;
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_ping_out;
else
role = role_pong_back;
//
// Address
//
if ( role == role_pong_back )
node_address = 1;
else
{
// Read the address from EEPROM
uint8_t reading = EEPROM.read(address_at_eeprom_location);
// If it is in a valid range for node addresses, it is our
// address.
if ( reading >= 2 && reading <= 6 )
node_address = reading;
// Otherwise, it is invalid, so set our address AND ROLE to 'invalid'
else
{
node_address = 0;
role = role_invalid;
}
}
//
// Print preamble
//
Serial.begin(57600);
printf_begin();
printf("\n\rRF24/examples/starping/\n\r");
printf("ROLE: %s\n\r",role_friendly_name[role]);
printf("ADDRESS: %i\n\r",node_address);
//
// Setup and configure rf radio
//
radio.begin();
//
// Open pipes to other nodes for communication
//
// The pong node listens on all the ping node talking pipes
// and sends the pong back on the sending node's specific listening pipe.
if ( role == role_pong_back )
{
radio.openReadingPipe(1,talking_pipes[0]);
radio.openReadingPipe(2,talking_pipes[1]);
radio.openReadingPipe(3,talking_pipes[2]);
radio.openReadingPipe(4,talking_pipes[3]);
radio.openReadingPipe(5,talking_pipes[4]);
}
// Each ping node has a talking pipe that it will ping into, and a listening
// pipe that it will listen for the pong.
if ( role == role_ping_out )
{
// Write on our talking pipe
radio.openWritingPipe(talking_pipes[node_address-2]);
// Listen on our listening pipe
radio.openReadingPipe(1,listening_pipes[node_address-2]);
}
//
// Start listening
//
radio.startListening();
//
// Dump the configuration of the rf unit for debugging
//
radio.printDetails();
//
// Prompt the user to assign a node address if we don't have one
//
if ( role == role_invalid )
{
printf("\n\r*** NO NODE ADDRESS ASSIGNED *** Send 1 through 6 to assign an address\n\r");
}
}
void loop(void)
{
//
// Ping out role. Repeatedly send the current time
//
if (role == role_ping_out)
{
// First, stop listening so we can talk.
radio.stopListening();
// Take the time, and send it. This will block until complete
unsigned long time = millis();
printf("Now sending %lu...",time);
radio.write( &time, sizeof(unsigned long) );
// Now, continue listening
radio.startListening();
// Wait here until we get a response, or timeout (250ms)
unsigned long started_waiting_at = millis();
bool timeout = false;
while ( ! radio.available() && ! timeout )
if (millis() - started_waiting_at > 250 )
timeout = true;
// Describe the results
if ( timeout )
{
printf("Failed, response timed out.\n\r");
}
else
{
// Grab the response, compare, and send to debugging spew
unsigned long got_time;
radio.read( &got_time, sizeof(unsigned long) );
// Spew it
printf("Got response %lu, round-trip delay: %lu\n\r",got_time,millis()-got_time);
}
// Try again 1s later
delay(1000);
}
//
// Pong back role. Receive each packet, dump it out, and send it back
//
if ( role == role_pong_back )
{
// if there is data ready
uint8_t pipe_num;
if ( radio.available(&pipe_num) )
{
// Dump the payloads until we've gotten everything
unsigned long got_time;
bool done = false;
while (!done)
{
// Fetch the payload, and see if this was the last one.
done = radio.read( &got_time, sizeof(unsigned long) );
// Spew it
printf("Got payload %lu from node %i...",got_time,pipe_num+1);
}
// First, stop listening so we can talk
radio.stopListening();
// Open the correct pipe for writing
radio.openWritingPipe(listening_pipes[pipe_num-1]);
// Retain the low 2 bytes to identify the pipe for the spew
uint16_t pipe_id = listening_pipes[pipe_num-1] & 0xffff;
// Send the final one back.
radio.write( &got_time, sizeof(unsigned long) );
printf("Sent response to %04x.\n\r",pipe_id);
// Now, resume listening so we catch the next packets.
radio.startListening();
}
}
//
// Listen for serial input, which is how we set the address
//
if (Serial.available())
{
// If the character on serial input is in a valid range...
char c = Serial.read();
if ( c >= '1' && c <= '6' )
{
// It is our address
EEPROM.write(address_at_eeprom_location,c-'0');
// And we are done right now (no easy way to soft reset)
printf("\n\rManually reset address to: %c\n\rPress RESET to continue!",c);
while(1) ;
}
}
}
// vim:ai:ci sts=2 sw=2 ft=cpp