The ForceTronics blog provides tutorials on creating fun and unique electronic projects. The goal of each project will be to create a foundation or jumping off point for amateur, hobbyist, and professional engineers to build on and innovate. Please use the comments section for questions and go to forcetronics.com for information on forcetronics consulting services.
Ever want to create a design that automates turning on or off an AC powered device such as a light or a heating system? Well this video is for you! In this video we look at how to create a development board for switching on and off AC power. The switch is implemented with a TRIAC which is a semiconductor device so no moving parts like a relay based design. You can access the Eagle PCB layout files from this link https://github.com/ForceTronics/AC-Switch-Proto-Board/tree/master or you can purchase this development board from www.forcetronics.com
Download Eagles files from GitHub: https://github.com/ForceTronics/AC-Switch-Proto-Board
*********************************Arduino code shown in the video********
//This sketch is used to control Thyristor that is used as a switch to turn on and off an AC line powered light. //This code is free for all to use
int8_t dig = 0; //default is high for light off
void setup() {
//for controlling Thyristor
pinMode(7, OUTPUT); //set pin to output so it can sink current from optoisolator
digitalWrite(7, HIGH); //when high the thyristor is off or open
}
void loop() {
delay(3000); //light turns on / off every 2 seconds
togLight(); //call function to turn light on / off using digital pin
In part 2 we focus on powering our wireless sensor node. We talk about batteries, battery sizing, estimating battery life, and battery monitoring. If you have any feedback or questions use the comments section below.
This is part 1 in a series where we look at how to build a large wireless network using Arduino and the nRF24L01+ Transceiver Modules. At the end of this series you will have a reference design for a wireless sensor development board and the code needed to turn the wireless sensor developments boards into a network. You will be able purchase all the hardware for this project at my site: www.forcetronics.com
In this video we give you an overview of the Atmel Xplained Mini which is a development board for the ATmega168PB microcontroller. In the video we cover how to load a simple "Blink" program onto the Xplained Mini with Atmel Studio and how the development board is compatible with Arduino Shields. The video is presented from the standpoint of an Arduino user. You can access the code from the video below.
//**************************Atmel Studio Code**************************** /* * ATmega168PB Example.c * * Created: 11/21/2015 4:59:24 PM * Author : ForceTronics */ #define F_CPU 16000000UL //Set the clock frequency #include <avr/io.h> //call IO library #include <util/delay.h> //call delay library int main(void) { DDRB |= (1<<DDB5); //Set Port B 5 or PB5 or PCINT5 or pin 17 to output (1 is output and 0 is input) while(1) { /* PORTB |= (1<<PORTB5); //Set PB5 to 1 which is high (LED on) _delay_ms(1000); //Delay for 1000ms or 1 sec PORTB &= ~(1<<PORTB5); //Set PB5 to 0 which is low (LED off) _delay_ms(1000); //Delay for 1000ms or 1 sec */ PINB |= (1<<PINB5); _delay_ms(1000); //Delay for 1000ms or 1 sec } }
In this video we give you an overview of the LM317 Voltage Regulator and how to configure it. The LM317 is popular voltage regulator among makers because of its low cost and its adjustable output voltage. You can purchase the LM317 at www.forcetronics.com
Ever want to remove the microcontroller off the Arduino board to better integrate it into your project or design. In this video we do just that with Atmel ATmega 328P MCU found on the Arduino Uno. We will look at the bare bones circuit setup needed to run the 328P as well as how to still program it with the Arduino IDE. All the parts shown in this video can be purchased from forcetronics.com.
The nRF24L01+ Transceiver is a great low cost way to add wireless capability to any project. But the down side of the nRF24L01+ is it can be a hassle to prototype with. In this video we look at how to build an Arduino shield and a mini proto board for the nRF24L01+. You can also purchase the shield and mini proto board covered in the video at forcetronics.com.
//*****************************Arduino Code for Transmitter***********************
//This sketch is from a tutorial video on the ForceTronics YouTube Channel. The tutorial discusses how to build a
//shield and a prototyping board for the nRF24L01 Transceiver Module.
//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/
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
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
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.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();
}
void loop()
{
byte t = analogRead(0);//note that we can cast the ADC value to a byte because we know the temp sensor is not going to return a value higher than 255
if (!wirelessSPI.write(&t, 1 )){ //if the send fails let the user know over serial monitor
Serial.println("packet delivery failed");
}
delay(1000);
}
//*****************************Arduino Code for Receiver***********************
//This sketch is from a tutorial video on the ForceTronics YouTube Channel. The tutorial discusses how to build a
//shield and a prototyping board for the nRF24L01 Transceiver Module.
//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/
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 bVal; //used to store ADC value payload from transmit module, the ADC value will be < 256 so it will fit in a byte
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
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.openReadingPipe(1,pAddress); //open pipe o for recieving meassages with pipe address
wirelessSPI.startListening(); // Start listening for messages
}
void loop()
{
//loop until all of the payload data is recieved, for this example loop should only run once
while(wirelessSPI.available()){
wirelessSPI.read( &bVal, 1 ); //read one byte of data and store it in bVal variable
Serial.print("Temperature at transmitter is ");
Serial.print(calculateTempF(calculateArduinoVolt(bVal))); //convert the ADC value to a voltage value and than to a temperature value in F
Serial.println(" F");
}
delay(200);
}
//this function calculates temp in F from TMP36 temp sensor
float calculateTempF(float v1) {
float temp = 0;
//calculate temp in C, .75 volts is 25 C. 10mV per degree
if (v1 < .75) { temp = 25 - ((.75-v1)/.01); } //if below 25 C
In this video we take a look at the digital to analog converter (DAC) on the Arduino Zero. We will look at a simple example how to use the DAC and then we will look at a more complex example that turns the DAC into a pseudo waveform generator. You can find the code from this video below.
//***************ZeroDACExample Sketch******************************* //This sketch provides an example on using the DAC on the Arduino Zero. //It was used in a video tutorial on the ForceTronics YouTube Channel. //This code is free and open for anybody to use and modify at their own risk void setup() { Serial.begin(57600); //start serial communication analogWriteResolution(10); //set the Arduino DAC for 10 bits of resolution (max) analogReadResolution(12); //set the ADC resolution to 12 bits, default is 10 //Get user entered voltage, convert to DAC value, output DAC value analogWrite(A0,setDAC(getVoltValue())); } void loop() { delay(2000); Serial.println(); Serial.print("Measured voltage value is "); Serial.println(convertToVolt(analogRead(A1))); //Read value at ADC pin A1 and print it } //this function converts a user entered voltage value into a 10 bit DAC value int setDAC(float volt) { //formula for calculating DAC output voltage Vdac = (dVal / 1023)*3.3V return (int)((volt*1023)/3.3); } //this function gets the user entered DAC voltage value from serial monitor float getVoltValue() { float v = 0; //variable to store voltage Serial.println("Enter the voltage you want the DAC to output (range 0V to 3.3V)"); v = readParameter(); if (v < 0 || v > 3.3) v = 0; //check to make sure it is between 0 and 3.3V Serial.print("DAC voltage set to "); Serial.println(v); Serial.println("Outputting DAC value........"); return v; } //waits for serial data and reads it in. This function reads in the parameters // that are entered into the serial terminal float readParameter() { while(!Serial.available()); //Wait for user to enter setting return Serial.parseFloat(); //get int that was entered on Serial monitor } //This function takes and ADC integer value (0 to 4095) and turns it into a voltage level. The input is the measured 12 bit ADC value. float convertToVolt(int aVAL) { return (((float)aVAL/4095)*3.3); //formula to convert ADC value to voltage reading }
//***************ZeroWaveGen Sketch************************************** //This sketch generates a sine wave on the Arduino Zero DAC based on user entered sample count and sample rate //It was used in a tutorial video on the ForceTronics YouTube Channel. This code can be used and modified freely //at the users own risk volatile int sIndex; //Tracks sinewave points in array int sampleCount = 100; // Number of samples to read in block int *wavSamples; //array to store sinewave points uint32_t sampleRate = 1000; //sample rate of the sine wave void setup() { analogWriteResolution(10); //set the Arduino DAC for 10 bits of resolution (max) getSinParameters(); //get sinewave parameters from user on serial monitor /*Allocate the buffer where the samples are stored*/ wavSamples = (int *) malloc(sampleCount * sizeof(int)); genSin(sampleCount); //function generates sine wave } void loop() { sIndex = 0; //Set to zero to start from beginning of waveform tcConfigure(sampleRate); //setup the timer counter based off of the user entered sample rate //loop until all the sine wave points have been played while (sIndex<sampleCount) { //start timer, once timer is done interrupt will occur and DAC value will be updated tcStartCounter(); } //disable and reset timer counter tcDisable(); tcReset(); } //This function generates a sine wave and stores it in the wavSamples array //The input argument is the number of points the sine wave is made up of void genSin(int sCount) { const float pi2 = 6.28; //2 x pi float in; for(int i=0; i<sCount;i++) { //loop to build sine wave based on sample count in = pi2*(1/(float)sCount)*(float)i; //calculate value in radians for sin() wavSamples[i] = ((int)(sin(in)*511.5 + 511.5)); //Calculate sine wave value and offset based on DAC resolution 511.5 = 1023/2 } } //This function handles getting and setting the sine wave parameters from //the serial monitor. It is important to use the Serial.end() function //to ensure it doesn't mess up the Timer counter interrupts later void getSinParameters() { Serial.begin(57600); Serial.println("Enter number of points in sine wave (range 10 to 1000)"); sampleCount = readParameter(); if (sampleCount < 10 || sampleCount > 1000) sampleCount = 100; Serial.print("Sample count set to "); Serial.println(sampleCount); Serial.println("Enter sample rate or samples per second for DAC (range 1 to 100k)"); sampleRate = readParameter(); if (sampleRate < 1 || sampleRate > 100000) sampleRate = 10000; Serial.print("Sample rate set to "); Serial.println(sampleRate); Serial.println("Generating sine wave........"); Serial.end(); } //waits for serial data and reads it in. This function reads in the parameters // that are entered into the serial terminal int readParameter() { while(!Serial.available()); return Serial.parseInt(); //get int that was entered on Serial monitor } // Configures the TC to generate output events at the sample frequency. //Configures the TC in Frequency Generation mode, with an event output once //each time the audio sample frequency period expires. void tcConfigure(int sampleRate) { // Enable GCLK for TCC2 and TC5 (timer counter input clock) GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5)) ; while (GCLK->STATUS.bit.SYNCBUSY); tcReset(); //reset TC5 // Set Timer counter Mode to 16 bits TC5->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16; // Set TC5 mode as match frequency TC5->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ; //set prescaler and enable TC5 TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1 | TC_CTRLA_ENABLE; //set TC5 timer counter based off of the system clock and the user defined sample rate or waveform TC5->COUNT16.CC[0].reg = (uint16_t) (SystemCoreClock / sampleRate - 1); while (tcIsSyncing()); // Configure interrupt request NVIC_DisableIRQ(TC5_IRQn); NVIC_ClearPendingIRQ(TC5_IRQn); NVIC_SetPriority(TC5_IRQn, 0); NVIC_EnableIRQ(TC5_IRQn); // Enable the TC5 interrupt request TC5->COUNT16.INTENSET.bit.MC0 = 1; while (tcIsSyncing()); //wait until TC5 is done syncing } //Function that is used to check if TC5 is done syncing //returns true when it is done syncing bool tcIsSyncing() { return TC5->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY; } //This function enables TC5 and waits for it to be ready void tcStartCounter() { TC5->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; //set the CTRLA register while (tcIsSyncing()); //wait until snyc'd } //Reset TC5 void tcReset() { TC5->COUNT16.CTRLA.reg = TC_CTRLA_SWRST; while (tcIsSyncing()); while (TC5->COUNT16.CTRLA.bit.SWRST); } //disable TC5 void tcDisable() { TC5->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE; while (tcIsSyncing()); } void TC5_Handler (void) { analogWrite(A0, wavSamples[sIndex]); sIndex++; TC5->COUNT16.INTFLAG.bit.MC0 = 1; }
In this video we look at how to do debugging with the Arduino Zero. The Arduino Zero has a lot of great capabilities and features. One of those great features is it has a built-in hardware debugger. In this video we will look at how to use the debugger and the software you need to go with it.
//***************Arduino Code from Video********************************** /* This code was used for a tutorial video on the ForceTronics YouTube Channel that showed how to do debugging with the Arduino Zero and Atmel Studio. This code is free and open for anybody to use or modify */ int ranNum; //global variable to hold random number void setup() { randomSeed(analogRead(A0)); //seed value for random number generator pinMode(13, OUTPUT); // initialize digital pin 13 as an output. } void loop() { ranNum = random(0,100); //generate a random number between zero and 100 digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(13, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second }
This video provides an overview of ForceTronics LLC's contracting and consulting services. Whether you are a maker, entrepreneur, or a startup Forcetronics Contracting and Consulting Services can help turn your idea into reality leveraging the power of open source hardware.
If you are interested contact me on twitter or email:
Twitter: @ForceTronics
Email: forcetronics@gmail.com
Put “Contracting Services” or “Consulting Services” in the subject line
Welcome to the final installment of building your own AVR / Arduino compatible internet of things (IoT) development board. In part 5 we open up our new PCBs and build them up. We then do some testing to make sure everything is working correctly. Spoiler alert, this video has a happy ending with a working Arduino compatible board with Bluetooth 4.0 built-in. Below you will find a link to the Eagle files and the Arduino code for the test sketch.
*******************Arduino Test Sketch************************************ //This sketch is to test a DIY Arduino compatiable board with Bluetooth 4.0 on it //the board is targeted IoT applications. Details can be found of the ForceTronics //YouTube channel. This code is open for anybody to use and modify int wValue = 1; //variable to hold write value (high or low) void setup() { Serial.begin(115200); //start serial } void loop() { delay(1000); setPinMode(OUTPUT, INPUT); //set D2 to D7 as outputs, and D8 to D13 to inputs setDigWrite(false, wValue); //set group of pins to write and write high or low Serial.print("D2 thru D7 writing "); Serial.println(wValue); Serial.println("D8 thru D13 reading the following values...."); printDigPins(true); //print what dig pins read delay(1000); setPinMode(INPUT, OUTPUT); //set D2 to D7 as intputs, and D8 to D13 to outputs setDigWrite(true, wValue); //set group of pins to write and write high or low Serial.print("D8 thru D13 writing "); Serial.println(wValue); Serial.println("D2 thru D7 reading the following values...."); printDigPins(false); //print what dig pins read delay(1000); adcReads(); //read each ADC pin and print result if(wValue) wValue = 0; //toggle digital write value else wValue = 1; delay(1000); } //function sets D2 thru D7 to input / output and D8 thru D13 to input / output void setPinMode(int smallMode, int bigMode) { for(int i=0;i<6;i++) { pinMode((i+2), smallMode); pinMode((i+8), bigMode); } } //Writes high or low to group of digital pins void setDigWrite(bool big, int state) { if(big) { for(int i=0;i<6;i++) { digitalWrite((i+8), state); } } else { for(int i=0;i<6;i++) { digitalWrite((i+2), state); } } } //does digital read on group of digital pins and prints results void printDigPins(bool big) { if(big) { for(int i=0;i<6;i++) { Serial.print("Value at pin D"); Serial.print((i+8)); Serial.print(" --> "); Serial.println(digitalRead((i+8))); } } else { for(int i=0;i<6;i++) { Serial.print("Value at pin D"); Serial.print((i+2)); Serial.print(" --> "); Serial.println(digitalRead((i+2))); } } } //Reads each ADC pin and prints result void adcReads() { for(int i=0; i<6; i++) { Serial.print("ADC value at Pin A"); Serial.print(i); Serial.print(" --> "); Serial.println(analogRead(i)); } }
In this video we take a brief look at how a transistor works and how to use it as a not gate or an digital logic inverter. We look at an example with Arduino using both an NPN and a PNP bipolar junction transistor as a not gate
//***********Arduino Code ****************************************** //This example code was used on the Forcetronics YouTube Channel to demonstrate how to //make an inverter or not gate using an NPN and PNP transistor const int NPN = 2; //create variable for NPN base const int PNP = 3; //create variable for PNP base const int NPNRead = 4; //create variable to read NPN const int PNPRead = 5; //create variable to read PNP void setup() { pinMode(NPN, OUTPUT); // set pin to output pinMode(PNP, OUTPUT); // set pin to output pinMode(NPNRead, INPUT); // set pin to input pinMode(PNPRead, INPUT); // set pin to input Serial.begin(9600); //start serial comm } void loop() { digitalWrite(NPN, LOW); // set NPN base to low digitalWrite(PNP, LOW); // set PNP base to low Serial.println("Base of NPN and PNP is set to Low"); Serial.print("NPN reads "); Serial.println(digitalRead(NPNRead)); //read and print value at NPN digital pin Serial.print("PNP reads "); Serial.println(digitalRead(PNPRead)); //read and print value at PNP digital pin Serial.println(); delay(1000); digitalWrite(NPN, HIGH); // set NPN base to high digitalWrite(PNP, HIGH); // set PNP base to high Serial.println("Base of NPN and PNP is set to High"); Serial.print("NPN reads "); Serial.println(digitalRead(NPNRead)); //read and print value at NPN digital pin Serial.print("PNP reads "); Serial.println(digitalRead(PNPRead)); //read and print value at PNP digital pin Serial.println(); delay(1000); }
In this video we cover briefly what a transistor is and discuss how to use them as an electrical switch (DC only). As a demonstration we use an Arduino to switch on and off an NPN transistor and a PNP transistor.
//************************Arduino Code ******************************
//This example code was used on the Forcetronics YouTube Channel to demonstrate how to
//make an inverter or not gate using an NPN and PNP transistor. This code is open for
//anybody to use or modify
const int BJT = 2; //create variable to control the base of NPN and PNP
void setup() {
pinMode(BJT, OUTPUT); // set it as digital output
}
void loop() {
digitalWrite(BJT, LOW); // set base of NPN and PNP to low
delay(1000);
digitalWrite(BJT, HIGH); // set base of NPN and PNP to high
delay(1000);
}
This is part 4 in a 5 part series where we build our own AVR / Arduino Internet of Things (IoT) development board, yay! In this part we will do the PCB layout and discuss how to get our PCB manufactured.
Eagle Parts and Libraries Libraries Used:
•Atmega 328P --> Library: SparkFun-DigitalIC Device: ATMEGA328P_PDIP
•LM317 --> Library: linear>*317 Device:317T
•Resonator ZTT16.0MHz --> Library: Adafruit Device: CERMOSCILL-THM (CERMOSCILL)
•Ceramic Cap --> Library: rcl > C-EU Device: C-EU050-030X075
•Electrolytic cap --> Library: rcl > CPOL-EU Device: CPOL-EUE2.5-6
•Resistor --> Library: resistor Device: R-EU_0207/10 (R-EU_) Package: 0207/10
•Reset switch --> Library: switch-omron Device: 10-XX
•LED --> Library: led Device: LED5MM (LED)
•Potentiometer --> Library: rcl > R-TRIMM Device: R-TRIMMT93YA
Note: Sparkfun and Adafruit libraries did not come with Eagle, but you can find them on their websites
Parts I made (included in files linked to my blog):
•ForceTronic.lbr --> All header and pin holes and 2.1mm DC Jack
•BLE_Micro_Module.lbr --> BLE Micro
This is part 3 in a 5 part series where we build our own AVR / Arduino Internet of Things (IoT) development board, yay! In this part we will finalize our design schematic and parts list so we are ready to do PCB layout in part 4.
This is part 2 in a 5 part series where we build our own AVR / Arduino Internet of Things (IoT) development board, yay! In this part we add the Arduino bootloader to our Atmega 328p as well as build and test a prototype of our design.
//*******************Arduino Code********************************************** /* This sketch is part of a video tutorial on the ForceTronics YouTube Channel for Building Your AVR/Arduino IoT Development Board which uses a Atmega 328p and a Bluetooth low energy module. The bluetooth module is connected to an Arduino and the Arduino is connected to an LED. This code is in the public domain. */ // Pin 13 has a LED connected to it int led = 13; // the setup routine runs once when you press reset: void setup() { Serial.begin(115200); // initialize the digital pin as an output and set it low initially pinMode(led, OUTPUT); digitalWrite(led, LOW); } // the loop routine runs over and over again forever: void loop() { delay(30); String t; //create an empty string to store messages from Android while(Serial.available()) { //keep reading bytes while they are still more in the buffer t += (char)Serial.read(); //read byte, convert to char, and append it to string } if(t.length()) { //if string is not empty do the following if(t == "on") { //if the string is equal to "on" then turn LED on digitalWrite(led, HIGH); //Set digital pin to high to turn LED on Serial.write("LED is on"); //Tell the Android app that the LED was turned on } else if (t == "off") { digitalWrite(led, LOW); Serial.write("LED is off"); } // turn the LED off by making the voltage LOW } }
In this video we will take a look at Bluetooth Low Energy or Bluetooth Smart and compare it to classic Bluetooth. From there we will look at how to get started with the BLE Micro module and look at how to communicate with it from an iOS device and another BLE Micro Module.
************************Arduino Code**************************************** /* This sketch is part of a video tutorial on the ForceTronics YouTube Channel for using the BLE Micro module which uses Bluetooth low energy. The bluetooth module is connected to an Arduino and the Arduino is connected to an LED. This code is in the public domain. */ // Pin 7 has a LED connected to it int led = 7; // the setup routine runs once when you press reset: void setup() { Serial.begin(115200); // initialize the digital pin as an output and set it low initially pinMode(led, OUTPUT); digitalWrite(led, LOW); } // the loop routine runs over and over again forever: void loop() { delay(30); String t; //create an empty string to store messages from Android while(Serial.available()) { //keep reading bytes while they are still more in the buffer t += (char)Serial.read(); //read byte, convert to char, and append it to string } if(t.length()) { //if string is not empty do the following if(t == "on") { //if the string is equal to "on" then turn LED on digitalWrite(led, HIGH); //Set digital pin to high to turn LED on Serial.write("LED is on"); //Tell the Android app that the LED was turned on } else if (t == "off") { digitalWrite(led, LOW); Serial.write("LED is off"); } // turn the LED off by making the voltage LOW } }
In this 5 part video series we will build our own AVR / Arduino Internet of Things (IoT) development board. We will go from a design concept to prototyping our design to PCB layout of our design all the way to a tested and finished development board.
Example parts order for this project (please note that this does not include all the parts)
In this video we take a look at the power needs or power profile of the nRF24L01+ Transceiver. We discuss how much power it draws in each mode and how to reduce or optimize its power consumption for battery powered projects or designs. Finally we pair the nRF24L01 with an Arduino utilizing sleep mode and look at their combined power profile.
************Arduino and nRF24L01 Low Power Example Sketch************* #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 <avr/sleep.h> #include <avr/wdt.h> /*WDT BYTE variables for setting timer value WDTO_15MS, WDTO_30MS, WDTO_60MS, WDTO_120MS, WDTO_250MS, WDTO_500MS, WDTO_1S, WDTO_2S, WDTO_4S, WDTO_8S */ 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 RF24 wirelessSPI(pinCE, pinCSN); // Create your nRF24 object or wireless SPI connection const uint64_t wAddress = 0xB00B1E50D2LL; // Pipe to write or transmit on const uint64_t rAddress = 0xB00B1E50B1LL; //pipe to recive data on void setup() { randomSeed(analogRead(0)); //create unique seed value for random number generation wirelessSPI.begin(); //Start the nRF24 module wirelessSPI.setRetries(15,10); wirelessSPI.openWritingPipe(wAddress); //open writing or transmit pipe wirelessSPI.openReadingPipe(1,rAddress); //open reading or recieve pipe wirelessSPI.stopListening(); //go into transmit mode } void loop() { byte randNumber = (byte)random(11); //generate random guess between 0 and 10 if (!wirelessSPI.write(&randNumber, 1)){ //if the write fails // delivery failed } delay(30); //delay for short time in normal mode wirelessSPI.powerDown(); //put nRF24L01 into power down mode delayWDT(WDTO_30MS); // Use WDT sleep delay function, argument is byte variable from WDT Library wirelessSPI.powerUp(); //power up the nRF24 } //This function serves as a power saving delay function. The argument is a Byte type variable that is used to set the delay time //The function sets up sleep mode in power down state. The function then sets up the WDT timer in interrupt mode and sets it. //It then puts the Arduino to sleep for the set time. Upon wake up the WDT and sleep mode are shut off void delayWDT(byte timer) { sleep_enable(); //enable the sleep capability set_sleep_mode(SLEEP_MODE_PWR_DOWN); //set the type of sleep mode. Default is Idle ADCSRA &= ~(1<<ADEN); //Turn off ADC before going to sleep (set ADEN bit to 0) WDTCSR |= 0b00011000; //Set the WDE bit and then clear it when set the prescaler, WDCE bit must be set if changing WDE bit WDTCSR = 0b01000000 | timer; //Or timer prescaler byte value with interrupt selectrion bit set wdt_reset(); //Reset the WDT sleep_cpu(); //enter sleep mode. Next code that will be executed is the ISR when interrupt wakes Arduino from sleep sleep_disable(); //disable sleep mode ADCSRA |= (1<<ADEN); //Turn the ADC back on } //This is the interrupt service routine for the WDT. It is called when the WDT times out. //This ISR must be in your Arduino sketch or else the WDT will not work correctly ISR (WDT_vect) { wdt_disable(); MCUSR = 0; //Clear WDT flag since it is disabled, this is optional } // end of WDT_vect
In this video we will look at how to create an nRF24L01 Transceiver module network (more than two). This is useful if you want to build a wireless sensor network or some type of wireless automation system that has multiple wireless nodes.
***************************Arduino Code for Receiver******************************* //This sketch is from a tutorial video for networking more than two nRF24L01 tranciever modules on the ForceTronics YouTube Channel //the code was leverage from the following code http://maniacbug.github.io/RF24/starping_8pde-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/ 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 daNumber = 0; //The number that the transmitters are trying to guess RF24 wirelessSPI(pinCE, pinCSN); // Declare object from nRF24 library (Create your wireless SPI) const uint64_t rAddress[] = {0xB00B1E50D2LL, 0xB00B1E50C3LL}; //Create pipe addresses for the 2 nodes to recieve data, the "LL" is for LongLong type const uint64_t wAddress[] = {0xB00B1E50B1LL, 0xB00B1E50A4LL}; //Create pipe addresses for the 2 nodes to transmit data, the "LL" is for LongLong type void setup() { randomSeed(analogRead(0)); //create unique seed value for random number generation daNumber = (byte)random(11); //Create random number that transmitters have to guess Serial.begin(57600); //start serial to communication Serial.print("The number they are trying to guess is: "); Serial.println(daNumber); //print the number that they have to guess Serial.println(); wirelessSPI.begin(); //Start the nRF24 module wirelessSPI.openReadingPipe(1,rAddress[0]); //open pipe o for recieving meassages with pipe address wirelessSPI.openReadingPipe(2,rAddress[1]); //open pipe o for recieving meassages with pipe address wirelessSPI.startListening(); // Start listening for messages } void loop() { byte pipeNum = 0; //variable to hold which reading pipe sent data byte gotByte = 0; //used to store payload from transmit module while(wirelessSPI.available(&pipeNum)){ //Check if recieved data wirelessSPI.read( &gotByte, 1 ); //read one byte of data and store it in gotByte variable Serial.print("Recieved guess from transmitter: "); Serial.println(pipeNum); //print which pipe or transmitter this is from Serial.print("They guess number: "); Serial.println(gotByte); //print payload or the number the transmitter guessed if(gotByte != daNumber) { //if true they guessed wrong Serial.println("Fail!! Try again."); } else { //if this is true they guessed right if(sendCorrectNumber(pipeNum)) Serial.println("Correct! You're done."); //if true we successfully responded else Serial.println("Write failed"); //if true we failed responding } Serial.println(); } delay(200); } //This function turns the reciever into a transmitter briefly to tell one of the nRF24s //in the network that it guessed the right number. Returns true if write to module was //successful bool sendCorrectNumber(byte xMitter) { bool worked; //variable to track if write was successful wirelessSPI.stopListening(); //Stop listening, stop recieving data. wirelessSPI.openWritingPipe(wAddress[xMitter-1]); //Open writing pipe to the nRF24 that guessed the right number if(!wirelessSPI.write(&daNumber, 1)) worked = false; //write the correct number to the nRF24 module, and check that it was recieved else worked = true; //it was recieved wirelessSPI.startListening(); //Switch back to a reciever return worked; //return whether write was successful }
***************************Arduino Code for Transmitter 1****************************
//This sketch is from a tutorial video for networking more than two nRF24L01 tranciever modules on the ForceTronics YouTube Channel
//the code was leverage from the following code http://maniacbug.github.io/RF24/starping_8pde-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/
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 wAddress = 0xB00B1E50D2LL; // Pipe to write or transmit on
const uint64_t rAddress = 0xB00B1E50B1LL; //pipe to recive data on
void setup()
{
Serial.begin(57600); //start serial to communicate process
randomSeed(analogRead(0)); //create unique seed value for random number generation
wirelessSPI.begin(); //Start the nRF24 module
wirelessSPI.openWritingPipe(wAddress); //open writing or transmit pipe
wirelessSPI.openReadingPipe(1,rAddress); //open reading or recieve pipe
wirelessSPI.stopListening(); //go into transmit mode
}
void loop()
{
if(!done) { //true once you guess the right number
byte randNumber = (byte)random(11); //generate random guess between 0 and 10
if (!wirelessSPI.write( &randNumber, 1 )){ //if the write fails let the user know over serial monitor
Serial.println("Guess delivery failed");
}
else { //if the write was successful
Serial.print("Success sending guess: ");
Serial.println(randNumber);
wirelessSPI.startListening(); //switch to recieve mode to see if the guess was right
unsigned long startTimer = millis(); //start timer, we will wait 200ms
bool timeout = false;
while ( !wirelessSPI.available() && !timeout ) { //run while no recieve data and not timed out
if (millis() - startTimer > 200 ) timeout = true; //timed out
}
if (timeout) Serial.println("Last guess was wrong, try again"); //no data to recieve guess must have been wrong
else { //we recieved something so guess must have been right
byte daNumber; //variable to store recived value
wirelessSPI.read( &daNumber,1); //read value
if(daNumber == randNumber) { //make sure it equals value we just sent, if so we are done
Serial.println("You guessed right so you are done");
done = true; //signal to loop that we are done guessing
}
else Serial.println("Something went wrong, keep guessing"); //this should never be true, but just in case
}
wirelessSPI.stopListening(); //go back to transmit mode
}
}
delay(1000);
}
***************************Arduino Code for Transmitter 2****************************
//This sketch is from a tutorial video for networking more than two nRF24L01 tranciever modules on the ForceTronics YouTube Channel
//the code was leverage from the following code http://maniacbug.github.io/RF24/starping_8pde-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/
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
bool done = false; //used to know when to stop sending guesses
RF24 wirelessSPI(pinCE, pinCSN); // Create your nRF24 object or wireless SPI connection
const uint64_t wAddress = 0xB00B1E50C3LL; //pipe for writing or transmitting data
const uint64_t rAddress = 0xB00B1E50A4LL; //pipe for reading or recieving data
void setup()
{
Serial.begin(57600); //start serial to communicate process
randomSeed(analogRead(0)); //create unique seed value for random number generation
wirelessSPI.begin(); //Start the nRF24 module
wirelessSPI.openWritingPipe(wAddress); // setup pipe to transmit over
wirelessSPI.openReadingPipe(1,rAddress); //set up pipe to recieve data
wirelessSPI.stopListening(); //turn off recieve capability so you can transmit
}
void loop()
{
if(!done) { //true once you guess the right number
byte randNumber = (byte)random(11); //generate random guess between 0 and 10
if (!wirelessSPI.write( &randNumber, 1 )){ //if the write fails let the user know over serial monitor
Serial.println("Guess delivery failed");
}
else { //if the write was successful
Serial.print("Success sending guess: ");
Serial.println(randNumber);
wirelessSPI.startListening(); //switch to recieve mode to see if the guess was right
unsigned long startTimer = millis(); //start timer, we will wait 200ms
bool timeout = false;
while ( !wirelessSPI.available() && !timeout ) { //run while no recieve data and not timed out
if (millis() - startTimer > 200 ) timeout = true; //timed out
}
if (timeout) Serial.println("Last guess was wrong, try again"); //no data to recieve guess must have been wrong
else { //we recieved something so guess must have been right
byte daNumber; //variable to store recived value
wirelessSPI.read( &daNumber,1); //read value
if(daNumber == randNumber) { //make sure it equals value we just sent, if so we are done
Serial.println("You guessed right so you are done");
done = true; //signal to loop that we are done guessing
}
else Serial.println("Something went wrong, keep guessing"); //this should never be true, but just in case
}
wirelessSPI.stopListening(); //go back to transmit mode