Introduction to C with Arduino

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!