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.
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