Monday, February 16, 2015

Getting Started with the nRF24L01 Transceiver

In this video we look at how to get up and running with the low cost nRF24L01+ transceiver module from Nordic.



nRF24L01 connected to an Arduino Pro Mini


***********Arduino code for transmit module*********************************
//This sketch is from a tutorial video for getting started with the nRF24L01 tranciever module on the ForceTronics YouTube Channel
//the code was leverage from Ping pair example at http://tmrh20.github.io/RF24/pingpair_ack_8ino-example.html
//This sketch is free to the public to use and modify at your own risk

#include <SPI.h> //Call SPI library so you can communicate with the nRF24L01+
#include <nRF24L01.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include <RF24.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include "printf.h" //This is used to print the details of the nRF24 board. if you don't want to use it just comment out "printf_begin()"

const int pinCE = 9; //This pin is used to set the nRF24 to standby (0) or active mode (1)
const int pinCSN = 10; //This pin is used to tell the nRF24 whether the SPI communication is a command or message to send out
byte counter = 1; //used to count the packets sent
bool done = false; //used to know when to stop sending packets
RF24 wirelessSPI(pinCE, pinCSN); // Create your nRF24 object or wireless SPI connection
const uint64_t pAddress = 0xB00B1E5000LL;              // Radio pipe addresses for the 2 nodes to communicate.

void setup()  
{
  Serial.begin(57600);   //start serial to communicate process
  printf_begin();        //This is only used to print details of nRF24 module, needs Printf.h file. It is optional and can be deleted
  wirelessSPI.begin();            //Start the nRF24 module
  wirelessSPI.setAutoAck(1);                    // Ensure autoACK is enabled so rec sends ack packet to let you know it got the transmit packet payload
  wirelessSPI.enableAckPayload();               // Allow optional ack payloads
  wirelessSPI.setRetries(5,15);                 // Sets up retries and timing for packets that were not ack'd, current settings: smallest time between retries, max no. of retries
  wirelessSPI.openWritingPipe(pAddress);        // pipe address that we will communicate over, must be the same for each nRF24 module
  wirelessSPI.stopListening();
  wirelessSPI.printDetails();                   // Dump the configuration of the rf unit for debugging
}


void loop()  
{

 if(!done) { //if we are not done yet
    Serial.print("Now send packet: "); 
    Serial.println(counter); //serial print the packet number that is being sent
    unsigned long time1 = micros();  //start timer to measure round trip
    //send or write the packet to the rec nRF24 module. Arguments are the payload / variable address and size
   if (!wirelessSPI.write( &counter, 1 )){  //if the send fails let the user know over serial monitor
       Serial.println("packet delivery failed");      
   }
   else { //if the send was successful 
      unsigned long time2 = micros(); //get time new time
      time2 = time2 - time1; //calculate round trip time to send and get ack packet from rec module
      Serial.print("Time from message sent to recieve Ack packet: ");
      Serial.print(time2); //print the time to the serial monitor
      Serial.println(" microseconds");
       counter++; //up the packet count
   }
   
   //if the reciever sends payload in ack packet this while loop will get the payload data
   while(wirelessSPI.available() ){ 
       char gotChars[5]; //create array to hold payload
       wirelessSPI.read( gotChars, 5); //read payload from ack packet
       Serial.print(gotChars[0]); //print each char from payload
       Serial.print(gotChars[1]);
       Serial.print(gotChars[2]);
       Serial.println(gotChars[3]);
       done = true; //the ack payload signals we are done
     }
  }

    delay(1000);
}

***********Arduino code for receiver module*********************************
//This sketch is from a tutorial video for getting started with the nRF24L01 tranciever module on the ForceTronics YouTube Channel
//the code was leverage from Ping pair example at http://tmrh20.github.io/RF24/pingpair_ack_8ino-example.html
//This sketch is free to the public to use and modify at your own risk

#include <SPI.h> //Call SPI library so you can communicate with the nRF24L01+
#include <nRF24L01.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include <RF24.h> //nRF2401 libarary found at https://github.com/tmrh20/RF24/
#include "printf.h" //This is used to print the details of the nRF24 board. if you don't want to use it just comment out "printf_begin()"

const int pinCE = 9; //This pin is used to set the nRF24 to standby (0) or active mode (1)
const int pinCSN = 10; //This pin is used to tell the nRF24 whether the SPI communication is a command or message to send out
byte gotByte = 0; //used to store payload from transmit module
bool done = false;
RF24 wirelessSPI(pinCE, pinCSN); // Declare object from nRF24 library (Create your wireless SPI) 
const uint64_t pAddress = 0xB00B1E5000LL;  //Create a pipe addresses for the 2 nodes to communicate over, the "LL" is for LongLong type

void setup()   
{
  Serial.begin(57600);  //start serial to communicate process
  printf_begin();  //This is only used to print details of nRF24 module, needs Printf.h file. It is optional and can be deleted
  wirelessSPI.begin();  //Start the nRF24 module
  wirelessSPI.setAutoAck(1);                    // Ensure autoACK is enabled, this means rec send acknowledge packet to tell xmit that it got the packet with no problems
  wirelessSPI.enableAckPayload();               // Allow optional payload or message on ack packet
  wirelessSPI.setRetries(5,15);                 // Defines packet retry behavior: first arg is delay between retries at 250us x 5 and max no. of retries
  wirelessSPI.openReadingPipe(1,pAddress);      //open pipe o for recieving meassages with pipe address
  wirelessSPI.startListening();                 // Start listening for messages
  wirelessSPI.printDetails();                   //print details of nRF24 module to serial, must have printf for it to print to serial
}

void loop()  
{   
    if(gotByte >= 9 & !done) { //once we get 10 packets send ack packet with payload telling the transmit module we are done
       char cArray[5] = "done"; //create char array to store "done," note that the fifth char is for the null character
       wirelessSPI.writeAckPayload(1, cArray, sizeof(cArray));  //send ack payload. First argument is pipe number, then pointer to variable, then variable size
     }
   //loop until all of the payload data is recieved, for this example loop should only run once
    while(wirelessSPI.available() & !done){ 
     wirelessSPI.read( &gotByte, 1 ); //read one byte of data and store it in gotByte variable
     Serial.print("Recieved packet number: "); //payload counts packet number
     Serial.println(gotByte); //print payload / packet number
    }
    
    if(gotByte > 9) done = true; //we are finished so set "done" to true
   
  delay(200);    
}

***********Arduino code for Printf.h file*********************************
/*
 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__

Monday, February 2, 2015

Getting Started with Digital Potentiomenters

In this video we will look at what Digital Potentiometers are, how to understand their specs, and we will go over an example setup with two digital potentiometers and Arduino.



********************Arduino Code*************************************************
//Example Arduino sketch used to control two digital potential in a video tutorial on the ForceTronics YouTube Channel
//This code is in the public domain and free for anybody to use at their own risk

#include "SPI.h" //SPI communication library

int nVolatile = 0b00100000; //status register value to store resistance value in non-volatile memory
int vWrite = 0b00000000; //status register to write resistance value (volatile)
int countPot1 = 0; //variable for MCP4161 dig pot value
int countPot2 = 0; //variable for MCP4131 dig pot value
int countDown1 = 0; //variable to control counting up and down for dig pot 1
int countDown2 = 0; //variable to control counting up and down for dig pot 2

void setup() {
  pinMode(6, OUTPUT);   //Set PWM pin to output 
  pinMode(2, OUTPUT);   //This pin controls SPI comm with dig pot 1
  pinMode(3, OUTPUT);   //This pin controls SPI comm with dig pot 2
  SPI.begin(); //Starts SPI communication
  analogWrite(6, 100); //Set pin 6 to PWM at 39 percent duty cycle
}

void loop() {
  writeToDigPot1(countPot1); //write resistance setting to dig pot 1
  writeToDigPot2(countPot2); //write resistance setting to dig pot 2

 if(!countDown1 & countPot1 < 255) { //If counting up and below 256 
   countPot1++; //up the resistance setting by 1
 }
 else { //time to count down now
  if(countPot1 > 0) { //if resistor setting is above 0
    countPot1--; //reduce resistor value
    countDown1 = 1; //remain in countdown mode
  } 
  else { //switch back to count up mode
    countPot1++; //up the resistance setting by 1
    countDown1 = 0; //set to count up mode
  }
 }

 if(!countDown2 & countPot2 < 70) { //If counting up and below 70
  countPot2++; //up the resistance setting by 1
 }
 else { //time to count down now
  if(countPot2 > 0) { //if resistor setting is above 0
    countPot2--; //reduce resistor value
    countDown2 = 1; //remain in countdown mode
  } 
  else { //switch back to count up mode
    countPot2++; //up the resistance setting by 1
    countDown2 = 0; //set to count up mode
  }
 }
  
  delay(8);
}

//This function handles the SPI communication to change resistor setting to dig pot 1
//input argument is resistance setting
void writeToDigPot1(int val) {
  digitalWrite(2, LOW);   //enable SPI comm to dig pot one
  digitalWrite(3, HIGH);  //disable SPI comm to dig pot 2
  delay(1); //short delay to ensure dig pins changed state
  SPI.transfer(vWrite); //status register set to write
  SPI.transfer(val); //write resistance value to dig pot
}

//This function handles the SPI communication to change resistor setting to dig pot 2
//input argument is resistance setting
void writeToDigPot2(int val) {
  digitalWrite(3, LOW);   //enable SPI comm to dig pot 2
  digitalWrite(2, HIGH);  //disable SPI comm to dig pot 1
  delay(1); //short delay to ensure dig pins changed state
  SPI.transfer(vWrite); //status register set to write
  SPI.transfer(val); //write resistance value to dig pot
}

//This function handles the SPI communication to set dig pot 1 value in non-volatile memory
//input argument is resistance setting
void writeDigPot1NV(int val) {
  digitalWrite(2, LOW);   //enable SPI comm to dig pot one
  digitalWrite(3, HIGH);  //disable SPI comm to dig pot 2
  delay(1); //short delay to ensure dig pins changed state
  SPI.transfer(nVolatile); //status register set to non-volatile write
  SPI.transfer(val); //write resistance value to dig pot
}