Libardunio reference
From Tinkerish
Contents |
basic usage
- edit libarduino.h and uncomment the #define ENABLE_<module_name> that corresponds to the functionality that you want to use
- add header file
#include <avr/io.h> #include <stdio.h> #include "libarduino.h" ...
modules
basic
simple pin I/O
Functions to manipulate and use the LED that is onboard Arduinos:
onboard_led_enable(); onboard_led_on(); onboard_led_off();
Functions to configure I/O pins:
setpin_in(DDRA, 1); /* make PORTA pin 1 (PA1) an input */ ... setpin_out(DDRB, 3); /* make PORTB pin 3 (PB3) an output pin*/
Functions to set I/O pins:
setpin(PORTA, 1); /* set PORTA pin 1 (PA1) to high */ ... clearpin(PORTB, 3); /* set PORTB pin 3 (PB3) to low */
arduino compatability
Aruduino terminology and raw AVR terminology is a bit different. The purpose of the ENABLE_ARDUINO_COMPAT is to be able to use a subset of the same functions that the Arduino project uses in its language. This may be useful if you want to read the labels (silkscreen) on your Arduino board and have it match the same references you are passing to the functions. If you don't want to use the same function names, libarduino already has functions to do all of the same stuff and is (in some cases) more efficient.
Arduino describes the pins as digital pins 0-13 and analog pins 0-6. Raw AVR and standard GNU avr-libc terminology groups the pins into ports. It references PORTB, PORTC, and PORTD, all who have pins 0-8. Individual pins are called PB0, PD4, etc. The I/O functions above use the standard raw AVR and GNU avr-libc type of terminalogy. If you would like to reference the silkscreen on an Aruduino and use the same functions that the arduino software does, the functions below are for you.
Note: currently only the small subset of basic Arduino functions are implemented. The intention of this library is not to be completely interface compatible with the Arduino language. The following are only provided because they are the most basic and greatly improve the usablity because of the silkscreen and labels that are on Arduino boards.
First, make sure that you uncomment the following to compile in these functions:
#define ENABLE_ARDUINO_COMPAT /* subset of arduino functions */
Next, you now have the following functions that you can use:
void pinMode(uint8_t pin, enum pinmode mode); void digitalWrite(uint8_t pin, enum pinstate value); uint8_t digitalRead(uint8_t pin); void analogWrite(uint8_t pin, uint8_t dutycycle); /* call pwm_init() first */
Now for some examples:
pinMode(12, OUTPUT);
pinMode(2, INPUT);
...
digitalWrite(12, HIGH);
...
digitalWrite(12, LOW);
...
while ( digitalRead(2) == LOW ) {;} /* wait until pin 2 goes high */
Also, the analogWrite() is implimented and can be used instead of the libarduino standard pwm_set(). Notice that pwm_init() still has to be called. Also, it uses a different reference for which PWM pin to use. It uses the same pin numbering that arduino uses. The standard pwm_*() functions that come with this library use PWM 1-4 as their reference (documented under the PWM module). It uses the pwm channel number used in all of the other libarduino pwm functions and is a number from 1-4. analogWrite() uses the standard arduino processing language reference by pin number. This does retract from the usefulness of this function.
pwm_init(1); ... analogWrite(9, dutycycle);
serial
First, enable the serial module in libarduino.h:
#define ENABLE_SERIAL
It is quite easy to use:
#include <stdio.h>
#include "libarduino.h"
...
serial_init();
...
printf("hello world\n\r");
...
c = getchar();
printf("you typed %d\n\r", c);
Now plug in your Arduino and give it a shot:
screen /dev/ttyUSB0 57600
pwm (LED brightness, motor, etc)
PWM is ideal for use in controlling the brightness of an LED or the speed of a DC motor. For anyone new to PWM, Google should have plenty of info for those not familiar with PWM. libarduino makes use of the AVR's built in hardware support for outputing PWM on specific pins. This allows us to not waste any valuable CPU cycles trying to manually bit bang I/O pins.
The basic concept here is that we can use it to vary the duty cycle of a signal on one of our PWM pins. If we make it so that that pin is off all of the time with a duty cycle of 0, the LED will be off all of the time. If we make it so that the signal is on all of the time with a duty cycle of 100% (using a value of 255 as described below), it will be at full brightness. If we choose a duty cycle betwen 1 and less than 100%, it will have a corresponding brightness value. The same concept applies to motor control except the motor will spin faster instead of the LED being brighter.
First, enable pwm in libraduino.h by uncommenting the following line:
#define ENABLE_PWM
There are 6 PWM pins that we can use (only 4 are supported so far). These are the same pins used by the PWM_SERVO module so they conflict with each other. It is possible to use servo channels 1 and 2 with one of these modules while using 3 and 4 with the other module.
- 1 - OC1A (avr pin 15 PB1) - arduino digital pin 9
- 2 - OC1B (avr pin 16 PB2) - arduino digital pin 10
- 3 - OC2A (avr pin 17 PB3) - arduino digital pin 11
- 4 - OC2B (avr pin 5 PD3) - arduino digital pin 3
To use it, we just init the PWM channel that we want to use and then we set the duration of the duty cycle we want output on the PWM pin. The duty cycle is any number from 0-255. 0 means that it will be off all of the time, 255 means it will be on all of the time, and any number in between will be on for a relative portion of time between 0-255.
pwm_init(1); /* initialize pwm on the first pwm channel arduino digital pin 9 */ ... pwm_set(1, dutycycle);
pwm servo
This modules lets one control standard servos with the PWM pins on an Arduino. Connect your servo as follows:
* Signal - connect to one of the pins listed below * VCC - connect to 5V power on your arduino or to external higher current power source * GND - connect to GND of your arduino (if you use an external VCC make sure you connect its GND as well)
First, enable the serial module in libarduino.h by uncommenting the following line:
#define ENABLE_PWMSERVO
There are 6 PWM pins that we can use (only 4 are supported so far). These are the same pins used by the regular PWM module so they conflict with each other. It is possible to use servo channels 1 and 2 with one of these modules while using 3 and 4 with the other module.
Available servo channels: * 1 - OC1A (avr pin 15 PB1) - arduino digital pin 9 (high resolution) * 2 - OC1B (avr pin 16 PB2) - arduino digital pin 10 (high resolution) * 3 - OC2A (avr pin 17 PB3) - arduino digital pin 11 (low resolution) * 4 - OC2B (avr pin 5 PD3) - arduino digital pin 3 (low resolution)
It is quite easy to use. Below we initialise servo #1. This is on Arduino digital pin 9 as described above. We then can set its position by calling pwmservo_set(). We give it a position between 0 and 255. 0 means the lowest position supported by the servo and 255 is the farthest position in the other direction. Servos 1 and 2 are controlled with a high resolution 16 bit timer counter. The other servos are controlled by 8 bit counters. libarduino takes care of scaling everything for us so that we may use the same interface for any of the servo types.
Here is an example:
#include "libarduino.h" ... pwmservo_init(1); ... pwmservo_set(1, position); /* position must be between 0 and 255 */
IR
IR, or infra-red, allows us to provide input to our AVR/Arduino using an IR remote control. The common household universal remote control can be used. This code was tested with a Vishay TSOP392 IR receiver. The have 3 pins, GND, PWR, and a signal pin. The signal pin is connected to INT0 on PD2. In Arduino speak, this is digital pin 2.
First, enable the IR (infrared) module in libarduino.h:
#define ENABLE_IR
Here is an example:
#include "libarduino.h"
...
ir_init();
...
c = ir_get(); /* blocks until we get a new value */
printf("got new command %d\n\r", c);
ADC (analog to digital convertor)
Arduinos have 6 ADC pins. One can use this to monitor battery voltages, sample audio, or use analog sensors (light, temperature, etc). Arduinos and AVRs have 10bits of ADC resolution. The default mode is to compare the voltage on the ADC pin to what is provided on AREF. Commonly, AREF is simply connected to VCC. If you input a voltage of 0v onto your ADC pin, adc_getval() will return 0. If you input a voltage equal to or greater than what is on AREF, you will get the highest 10 bit value, or 1024. Anything in between will yield a result in between.
For adc_get(), you will need to pass it a number that corresponds to which analog input you will be using. On both the Arduino and AVR datasheets they are numbered 0 through 5.
Note: you must use a wire to connect AREF to 5V or adc_get() will not work.
First, enable the ADC module in libarduino.h:
#define ENABLE_ADC
Here is an example:
#include "libarduino.h"
...
uint16_t val;
...
adc_init();
...
val = adc_get(0); /* blocks until we get a new value from analog input 0 */
printf("new analog value %d\n\r", val);
extras
timer counter overflow frequencies
The most common way of scheduling something to happen periodically is to use a timer counter. Basically, an interrupt fires when the timer counter does an overflow. First, you set up the timer counter to overflow as often as you want and then you do what you want in the corresponding overflow ISR. For convenience, timer counter configuration can be made easier with timercountercalcs.h. The things defined in this file make it easy to configure the timer counters. This is done by setting how often the overflow. Each timer counter has different settings. This is due to the different sizes of the counters and the values of the clock select registers. One should look at this file to see what all of the options are.
#include "timercountercalcs.h"
For instance, if you want to set timer counter 0 to overflow every 128useconds, one would do:
timercounter0_setoverflow(OVERFLOW_TC0_128US);
If you wanted to set timer counter 1 to overflow about every seconds, one could use:
timercounter1_setoverflow(OVERFLOW_TC1_1049MS);
It should be noted here that these are not the only times that are available. One can get the timer counters to overflow at different times than the defaults. By default, they overflow when they reach the TOP. This is normally all 1's. They support other modes where one can specify a value lower than the default TOP in an OCR register. Consult the AVR datasheet for more info.
