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.
Sunday, March 27, 2016
How to Protect your Arduino Design (Electrically) Part 1
In this video we look at how to protect your Arduino against different forms of electrical damage and ensure your design is electrically rugged. We will be looking at parts such as current limiting resistors, zenor diodes, and schottky barrier diodes.
Tuesday, March 15, 2016
Building a Wireless Sensor Network with the nRF24L01 Part 5
In Part 5 of building a wireless sensor network with Arduino and the nRF24L01+ transceiver we take a look at our brand new PCB boards and look at the code for adding the DS18S20 and the STTS751 temperature sensors to the design. You can access the PCB Eagle files and the Arduino code from GitHub: https://github.com/ForceTronics/nRF24L01_Wireless_Sensor_Dev_Board
Monday, February 8, 2016
The Watchdog Timer on Arduino
In this video we take a look at the Watchdog Timer on Arduino and the three different ways to configure it. We show a simple example using the Watchdog Timer and you can find the code from the example below.
//**********************Arduino Code*******************************
#include <avr/wdt.h> //Watch dog timer functions
#include <EEPROM.h> //library for using EEPROM
// Pin 13 has an LED connected on most Arduino boards.
int led = 13;
volatile int wSetting = 1; //variable to store WDT setting, make it volatile since it will be used in ISR
void setup() {
wdt_disable(); //Datasheet recommends disabling WDT right away in case of low probabibliy event
pinMode(led, OUTPUT); //set up the LED pin to output
pinMode(2,INPUT_PULLUP); //setup pin 2 for input since we will be using it with our button
getSettings(); //start serial settings menu to choose WDT setting
//setup the watchdog Timer based on the setting
if(wSetting == 1) setWDT(0b01000000); //set for interrupt
else if(wSetting == 2) setWDT(0b00001000); //set for reset
else setWDT(0b01001000); //set for interrupt and then reset
}
void loop() {
if(!digitalRead(2)) { //check if button to reset WDT was pressed
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
wdt_reset(); //Reset the WDT
}
}
//This function gets the WDT setting from the user using Serial comm
void getSettings() {
Serial.begin(57600);
Serial.println("We just started up......");
byte b; //variable to store interrupt / reset tracker
if(EEPROM.get(10, b)) { //check if interrupt occurred before reset
Serial.println("...and an interrupt occurred.....");
b = 0; //reset variable
EEPROM.put(10,b);
}
Serial.println("Select the WDT setting: 1 --> interrupt, 2 --> reset, 3 --> interrupt and reset");
//wait for user to input setting selection
while (!Serial.available()) { }
wSetting = Serial.parseInt(); //get entry and ensure it is valid
if(wSetting < 1 || wSetting > 3) {
wSetting = 1;
}
Serial.print("WDT setting is ");
Serial.println(wSetting);
Serial.println();
Serial.end(); //don't want to mix serial comm and interrupts together
}
/*
void setSleepInterval(byte timer) {
sleep_enable(); //enable the sleep mode
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //set the type of sleep mode. Default is Idle. power down saves the most power
ADCSRA &= ~(1<<ADEN); //Turn off ADC before going to sleep (set ADEN bit to 0). this saves even more power
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; //This sets the WDT to the interval specified in the function argument
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 function setups up and starts the watchdog timer
void setWDT(byte sWDT) {
WDTCSR |= 0b00011000;
WDTCSR = sWDT | WDTO_2S; //Set WDT based user setting and for 2 second interval
wdt_reset();
}
//This is the interrupt service routine for the WDT. It is called when the WDT times out and is in interrupt mode.
//This ISR must be in your Arduino sketch or else the WDT will not work correctly
ISR (WDT_vect)
{
digitalWrite(led, HIGH);
if(wSetting == 3) {
byte b = 1;
EEPROM.put(10, b);
}
//wdt_disable();
} // end of WDT_vect
//**********************Arduino Code*******************************
#include <avr/wdt.h> //Watch dog timer functions
#include <EEPROM.h> //library for using EEPROM
// Pin 13 has an LED connected on most Arduino boards.
int led = 13;
volatile int wSetting = 1; //variable to store WDT setting, make it volatile since it will be used in ISR
void setup() {
wdt_disable(); //Datasheet recommends disabling WDT right away in case of low probabibliy event
pinMode(led, OUTPUT); //set up the LED pin to output
pinMode(2,INPUT_PULLUP); //setup pin 2 for input since we will be using it with our button
getSettings(); //start serial settings menu to choose WDT setting
//setup the watchdog Timer based on the setting
if(wSetting == 1) setWDT(0b01000000); //set for interrupt
else if(wSetting == 2) setWDT(0b00001000); //set for reset
else setWDT(0b01001000); //set for interrupt and then reset
}
void loop() {
if(!digitalRead(2)) { //check if button to reset WDT was pressed
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
wdt_reset(); //Reset the WDT
}
}
//This function gets the WDT setting from the user using Serial comm
void getSettings() {
Serial.begin(57600);
Serial.println("We just started up......");
byte b; //variable to store interrupt / reset tracker
if(EEPROM.get(10, b)) { //check if interrupt occurred before reset
Serial.println("...and an interrupt occurred.....");
b = 0; //reset variable
EEPROM.put(10,b);
}
Serial.println("Select the WDT setting: 1 --> interrupt, 2 --> reset, 3 --> interrupt and reset");
//wait for user to input setting selection
while (!Serial.available()) { }
wSetting = Serial.parseInt(); //get entry and ensure it is valid
if(wSetting < 1 || wSetting > 3) {
wSetting = 1;
}
Serial.print("WDT setting is ");
Serial.println(wSetting);
Serial.println();
Serial.end(); //don't want to mix serial comm and interrupts together
}
/*
void setSleepInterval(byte timer) {
sleep_enable(); //enable the sleep mode
set_sleep_mode(SLEEP_MODE_PWR_DOWN); //set the type of sleep mode. Default is Idle. power down saves the most power
ADCSRA &= ~(1<<ADEN); //Turn off ADC before going to sleep (set ADEN bit to 0). this saves even more power
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; //This sets the WDT to the interval specified in the function argument
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 function setups up and starts the watchdog timer
void setWDT(byte sWDT) {
WDTCSR |= 0b00011000;
WDTCSR = sWDT | WDTO_2S; //Set WDT based user setting and for 2 second interval
wdt_reset();
}
//This is the interrupt service routine for the WDT. It is called when the WDT times out and is in interrupt mode.
//This ISR must be in your Arduino sketch or else the WDT will not work correctly
ISR (WDT_vect)
{
digitalWrite(led, HIGH);
if(wSetting == 3) {
byte b = 1;
EEPROM.put(10, b);
}
//wdt_disable();
} // end of WDT_vect
Labels:
arduino,
ATmega328P,
avr,
interrupt,
sleep,
Tutorial,
Watchdog Timer,
WDT
Sunday, January 31, 2016
How to Reset Your Arduino from Code
In this video we talk about how to reset your Arduino from code with no hands. You can find the schematic and code from this video below.
int led = 13;
//create a variable for detecting what mode you are in. If used in interrupt must be "volatile"
/*volatile*/ bool nMode = 1;
void setup() {
pinMode(4, OUTPUT); //set up pin 4, which is connected to base of transistor
digitalWrite(4,LOW); //set to low so transistor is off and doesn't trigger reset
pinMode(led, OUTPUT); //set up the LED pin to output
Serial.begin(57600); //start serial comm
Serial.println("We just started back up"); //print quick message so we know we just went through setup code
Serial.println();
Serial.end(); //need to shut off serial comm because it uses interrupts
//Create interrupt: 0 for pin 2, the name of the interrupt function or ISR, and condition to trigger interrupt
attachInterrupt(0, interruptFunction, CHANGE);
}
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(400); // wait
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(400); // wait
/*
noInterrupts(); //disables interrupts
// critical, time-sensitive code here
interrupts();//enables interrupts
*/
}
//This is the function called when the interrupt occurs (pin 2 goes high)
//this is often referred to as the interrupt service routine or ISR
//This cannot take any input arguments or return anything
void interruptFunction() {
digitalWrite(4,HIGH); //with this variable set to 1 the LED will blink
//detachInterrupt(0); this function call will turn the interrupt off
}
***************Arduino Code from Video************************************
// Pin 13 has an LED connected on most Arduino boards.int led = 13;
//create a variable for detecting what mode you are in. If used in interrupt must be "volatile"
/*volatile*/ bool nMode = 1;
void setup() {
pinMode(4, OUTPUT); //set up pin 4, which is connected to base of transistor
digitalWrite(4,LOW); //set to low so transistor is off and doesn't trigger reset
pinMode(led, OUTPUT); //set up the LED pin to output
Serial.begin(57600); //start serial comm
Serial.println("We just started back up"); //print quick message so we know we just went through setup code
Serial.println();
Serial.end(); //need to shut off serial comm because it uses interrupts
//Create interrupt: 0 for pin 2, the name of the interrupt function or ISR, and condition to trigger interrupt
attachInterrupt(0, interruptFunction, CHANGE);
}
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(400); // wait
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(400); // wait
/*
noInterrupts(); //disables interrupts
// critical, time-sensitive code here
interrupts();//enables interrupts
*/
}
//This is the function called when the interrupt occurs (pin 2 goes high)
//this is often referred to as the interrupt service routine or ISR
//This cannot take any input arguments or return anything
void interruptFunction() {
digitalWrite(4,HIGH); //with this variable set to 1 the LED will blink
//detachInterrupt(0); this function call will turn the interrupt off
}
Wednesday, January 27, 2016
Utilizing the Arduino ADC Internal Reference
In this video we look at the ADC internal reference in an Arduino, why / when would you use it, how to ensure you get good measurement accuracy when using it, and how to use it to check your battery voltage.
**********************Arduino Code from the video****************************
float iREF = 1.08; //internal reference cal factor
void setup() {
// put your setup code here, to run once:
analogReference(EXTERNAL);
//burn some ADC readings after reference change
for(int i=0; i<8; i++) analogRead(A0);
Serial.begin(57600);
}
void loop() {
// put your main code here, to run repeatedly:
delay(3000);
Serial.print("Measured battery voltage is: ");
Serial.println(fReadVcc());
Serial.println();
}
//This function uses the known internal reference value of the 328p (~1.1V) to calculate the VCC value which comes from a battery
//This was leveraged from a great tutorial found at https://code.google.com/p/tinkerit/wiki/SecretVoltmeter?pageId=110412607001051797704
float fReadVcc() {
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(3); //delay for 3 milliseconds
ADCSRA |= _BV(ADSC); // Start ADC conversion
while (bit_is_set(ADCSRA,ADSC)); //wait until conversion is complete
int result = ADCL; //get first half of result
result |= ADCH<<8; //get rest of the result
float batVolt = (iREF / result)*1024; //Use the known iRef to calculate battery voltage
return batVolt;
}
**********************Arduino Code from the video****************************
float iREF = 1.08; //internal reference cal factor
void setup() {
// put your setup code here, to run once:
analogReference(EXTERNAL);
//burn some ADC readings after reference change
for(int i=0; i<8; i++) analogRead(A0);
Serial.begin(57600);
}
void loop() {
// put your main code here, to run repeatedly:
delay(3000);
Serial.print("Measured battery voltage is: ");
Serial.println(fReadVcc());
Serial.println();
}
//This function uses the known internal reference value of the 328p (~1.1V) to calculate the VCC value which comes from a battery
//This was leveraged from a great tutorial found at https://code.google.com/p/tinkerit/wiki/SecretVoltmeter?pageId=110412607001051797704
float fReadVcc() {
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(3); //delay for 3 milliseconds
ADCSRA |= _BV(ADSC); // Start ADC conversion
while (bit_is_set(ADCSRA,ADSC)); //wait until conversion is complete
int result = ADCL; //get first half of result
result |= ADCH<<8; //get rest of the result
float batVolt = (iREF / result)*1024; //Use the known iRef to calculate battery voltage
return batVolt;
}
Wednesday, January 20, 2016
Building a Wireless Sensor Network with the nRF24L01 Part 4
In part 4 of Building a Wireless Sensor Network with the nRF24L01 we take a look at the design's PCB layout in Eagle software as well as cover some software and hardware updates to the design.
You can access the updated code and PCB files from GitHub: https://github.com/ForceTronics/nRF24L01_Wireless_Sensor_Dev_Board
You can access the updated code and PCB files from GitHub: https://github.com/ForceTronics/nRF24L01_Wireless_Sensor_Dev_Board
Wednesday, January 6, 2016
Building a Wireless Sensor Network with the nRF24L01 Part 3
In part three we take a look at the updated hardware schematic of the router / end device design, how the router / end device settings work, and we go over the initial software of the router / end device. You can find the code from this video in GitHub at https://github.com/ForceTronics/nRF24L01_Wireless_Sensor_Dev_Board
Subscribe to:
Posts (Atom)

