Hello! In this blog post, we will take a look at some basic C using Arduino. The code is available at https://github.com/jod75/basicarduino. The purpose of this post is not to show you how to use Arduino, but to help you get started with C. Clounce is working on some exiting Arduino projects, which he will share with you later.
For the intended purposes of this exercise, we will use Arduino’s serial monitor to show the output of our data manipulation. The Serial Monitor is an important tool, as it can be used to write data to a monitor to see what is going on in your embedded program.
All Arduino programs have two functions, a setup() and a loop(). As their name implies, setup() is used to initialize any objects or peripherals while loop() is the main function that our Arduino calls in succession.
The following is out setup(). We will initialize the Serial port and display the “Hello World!” message.
void setup() { // initialise serial communication // we will use 9600 baud rate // and default config = 8N1 (8-buts for data, no parity, and 1 stop bit) Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } // send an intro message // this is a must for learning a new language! Serial.println("\nHello World!"); Serial.println(); // like adding a \n at the end of the previous string }
Next we write our loop() function. Follow the comments to understand what is going on in the code.
void loop() { //---------------------------------------------------------------------------------------------- // let's experiment a bit with C variables // The size of an int, unsigned int, short, and a word are the same on Arduino UNO (On Due, int has different size) String message = String("byte sizes:\n"); message.concat("\t int = " + String(sizeof(int)) + "bytes\n"); message.concat("\t word = " + String(sizeof(word)) + "bytes\n"); message.concat("\t short = " + String(sizeof(short)) + "bytes\n"); message.concat("\t unsigned int = " + String(sizeof(unsigned int)) + "bytes\n"); message.concat("\t long = " + String(sizeof(long)) + "bytes\n"); message.concat("\t unsigned long = " + String(sizeof(unsigned long)) + "bytes\n"); message.concat("\t float = " + String(sizeof(float)) + "bytes\n"); message.concat("\t double = " + String(sizeof(double)) + "bytes\n"); Serial.println(message); Serial.println("\n\n----------------------------------------------\n\n"); // pretty dividers! // Hexadecimal and binary representations are frequently used for representing flags and switches // Displaying them is easy with Arduino's String library int value = 175; // 175 base 10 String hexValue = String(value, HEX); hexValue.toUpperCase(); message = String(String(value) + " = 0x" + hexValue); Serial.println(message); String binaryValue = String(value, BIN); Serial.println(String(value) + " = " + binaryValue + " in binary format"); Serial.println("\n\n----------------------------------------------\n\n"); // pretty dividers! // Let's talk arrays char msg[] = "This is a c string"; int len = sizeof(msg) / sizeof(char); Serial.println("Our c string has a length of " + String(len)); // print the message but make it funny for (int i = 0; i < len; i++) { String letter = String(msg[i]) + " "; if (isOdd(i)) letter.toUpperCase(); else letter.toLowerCase(); Serial.print(letter); } Serial.println("\n\n----------------------------------------------\n\n"); // pretty dividers! // array of string char* names[] = {"Clounce", "Arduino", "C"}; Serial.println("There are " + String(sizeof(names)/sizeof(names[0])) + " elements in names array!"); Serial.println("\n\n----------------------------------------------\n\n"); // pretty dividers! // sometimes we need to store data in arrays and then get some statistics // here we fill up an array of 24 floating point numbers, representing the temperature in degrees // Celsius on the hour for 1 day. Then we find the average temperature for that day. float temperature[] = {10.0, 9.9, 9.8, 9.7, 9.9, 10.1, 10.5, 11.1, 12.7, 13.0, 13.5, 14.2, 13.7, 14.5, 14.7, 14.0, 14.2, 14.0, 13.7, 13.8, 13.2, 12.7, 12.3, 11.9}; float total = 0.0; // we can either assume that we have 24 entries in 1 day, or else compute it. The latter is a better // choice, as we do not have to change our code if we decide to sample temperature every 30mins // instead every hour. len = sizeof(temperature) / sizeof(float); for(int i = 0; i < len; i++) total += temperature[i]; Serial.println("Average temperature is " + String(total / len) + " degrees Celsius."); Serial.println("\n\n----------------------------------------------\n\n"); // pretty dividers! // Bit manipulation is also important. Here we show how to do basic operations. for(int i = 0; i < 5; i++) { int x = random(3, 1000); Serial.println("Random value: " + String(x)); Serial.println(" : " + String(x, BIN)); Serial.println(" bit 0: " + String(bitRead(x, 0))); Serial.println(" bit 1: " + String(bitRead(x, 1))); if (bitRead(x, 2)) Serial.println(" bit 2: is set!"); else Serial.println(" bit 2: is NOT set!"); } Serial.println("\n\n----------------------------------------------\n\n"); // pretty dividers! // binary fun int x = 0; for (int i = 0; i < 8; i++) { int j = x | 1 << i; Serial.println(toBinary(j)); } Serial.println("\n\n----------------------------------------------\n\n"); // pretty dividers! Serial.println("Bye bye!"); while (true); // block here }
The String() object from Arduino’s library is a versatile class. You can use it to display integers in hexadecimal, octal, or binary format. One issue with displaying a binary number with this class is that it does not show the leading zeros. For example, if we have an integer value of 2, it will display 10. However, sometimes we are interested in displaying all bits in our integer. As we see when we run the code, an int type on Arduino Uno has a length of 2 bytes, that is, 16 bits. Thus, we want to show 2 as 0000000000000010. To do this, we can either simply add a number of 0s to our string representation or else, since, we are studying C, we use some shift operators. Clounce decided to go for the latter! Here’s the code to do this.
String toBinary(int number) { String output = ""; for (unsigned int i = (1 << (sizeof(number)*8)-1); i; i >>= 1) output.concat(number & i ? '1' : '0'); return output; }
In the toBinary() method, we build a string of 1s and 0s using binary masks. The loop, although looks scary, is very simple. The starting value of i is the binary number 1000000000000000, and the loop ends at i, that is, when i = 0 (false). With each iteration, we shift the 1 to the left. For example, after the second iteration the value of i becomes 0100000000000000. Bitwise anding our value with each value of i, then we can create our binary string.
Below is the output of one run from our code:
Hello World! byte sizes: int = 2bytes word = 2bytes short = 2bytes unsigned int = 2bytes long = 4bytes unsigned long = 4bytes float = 4bytes double = 4bytes ---------------------------------------------- 175 = 0xAF 175 = 10101111 in binary format ---------------------------------------------- Our c string has a length of 19 t H i S I s a c s T r I n G --------------------------------------------- There are 3 elements in names array! ---------------------------------------------- Average temperature is 12.38 degrees Celsius. ---------------------------------------------- Random value: 858 : 1101011010 bit 0: 0 bit 1: 1 bit 2: is NOT set! Random value: 227 : 11100011 bit 0: 1 bit 1: 1 bit 2: is NOT set! Random value: 672 : 1010100000 bit 0: 0 bit 1: 0 bit 2: is NOT set! Random value: 382 : 101111110 bit 0: 0 bit 1: 1 bit 2: is set! Random value: 586 : 1001001010 bit 0: 0 bit 1: 1 bit 2: is NOT set! ---------------------------------------------- 0000000000000001 0000000000000010 0000000000000100 0000000000001000 0000000000010000 0000000000100000 0000000001000000 0000000010000000 ---------------------------------------------- Bye bye!