Home

Awesome

PRismino library

This document explains the usage of the library to be used with the PRismino and Robopoly Shield. These are additional functions to complement Arduino functions.

Warning: some pins are hard-wired to elements that source current, this means that if the pins are set as outputs short-circuits can occur and damage the micro-controller, please read everything carefully to avoid it or you might break your PRismino.

Installing

Installing the library is like with any Arduino library, just copy /libraries and /hardware directories to your sketchbook directory:

For example the prismino.h file of this library should be under ~/Documents/Arduino/libraries/PRismino/. Once copied restart Arduino IDE.

Motor functions

Wheels/H-bridge

void setSpeed(int8_t leftSpeed, int8_t rightSpeed);

// set the left wheel forward 40% and right wheel backwards 40%
setSpeed(40, -40);

Defines the motor speed in percent from -100 to 100 trough the H-bridge. It uses the pins 9, 10, 11 and 12 of the PRismino. The speed is defined by a PWM signal with a period of 15'625Hz. This function uses the 10-bit Timer/Counter 4 of the ATmega32U4. In order to change direction interrupt vectors select which pin must be toggled.

In order for the command to take effect a short delay is required between 2 setSpeed() commands, 100ms (delay(100)) works quite well. This is typically needed for closed-loop regulation system where fast setSpeed() calls won't have the desired effect when called too often.

The H-bridge component is the DRV8833 which allows slow and fast decay modes, the library uses the fast decay mode by default. To select the slow decay mode one can define SLOWDECAY before including prismino.h file, or uncomment it in the prismino.h file.

// use the slow decay mode instead of fast decay
#define SLOWDECAY
#include <prismino.h>

The H-bridge can deliver 2A per channel, it is temperature regulated so if it overheats it will automatically stop and wait until the IC temperature gets low enough to restart. The absolute maximum voltage of the H-bridge is 11.8V, ideally do not exceed 10.8V as per the datasheet.

Stepper motor

One bipolar stepper motor can be controlled via the Stepper class and the dual H-bridge on the shield. The same timer/counter than for the DC motors is used since DC motors cannot be used at the same time anyway.

The available methods of the Stepper class are:

void Stepper::setPosition(int16_t position);

// set reference position to 20, this does not actually move the stepper motor
Stepper myStepper;
myStepper.setPosition(100, 50);

Sets the reference position, can be used to "reset" the postion to 0. One position equals to one commutation, the angle depends on the stepper motor step number.

int16_t Stepper::getPosition(void);

// get reference position
Stepper myStepper;
uint16_t stepperPosition = myStepper.getPosition();

Returns the current stepper motor position.

void Stepper::moveSteps(int16_t steps, uint16_t frequancy);

// move 100 steps clockwise at a speed of 50Hz, the actual movement depends on step angle
Stepper myStepper;
myStepper.moveSteps(100, 50);

Moves the stepper motor the amount of steps requested, the coil commutation happens at the requested frequency, the actual speed depends on the number of steps of the stepper motor. For example to get a rotational speed of 3RPM with a stepper having 400 steps one would need to set the commutation frequency to 3*400/60=20Hz. This is a non-blocking method.

uint8_t Stepper::isBusy(void);

Stepper myStepper;
myStepper.moveSteps(100, 50);
// while the stepper is completing its task one can do other things
while(myStepper.isBusy())
{
    // do other stuff
}

Once Stepper::moveSteps is called the stepper motor will complete the requested number of steps at the requested speed, it's not a blocking method so other things can be done at the same time, to check if the motor has finished one can poll Stepper::isBusy.

Button/switch functions

DIP-switch

void dipSwitch(uint8_t dip, void (*userFunc)(void), int mode);

// call a function when switch 1 is toggled
void myFunction(void)
{
    // ...
}
dipSwitch(DIP1, myFunction, CHANGE);

// call a function when switch 2 logic level goes from 1 to 0 (falling edge)
void myFunction2(void)
{
    // ...
}
dipSwitch(DIP2, myFunction2, FALLING);

Registers the callback function when a DIP-switch is toggled, it's actually a macro to attachInterrupt() Arduino function. It is best to call it in the initial setup part of the code (inside the setup() function). Different modes are:

The callback function cannot have any arguments.

The switches are located on pins 0 to 3, so when they are soldered the pins cannot be used in output mode.

The DIP* definitions help to find the right switch, they should be used instead of the pin numbers.

SwitchDefinitionValue (pin)
1DIP10
2DIP21
3DIP33
4DIP42

Note: the 2nd version of the shield only has 2 switches instead of 4, so DIP3 and DIP4 can't to be used anymore. Instead these pins are dedicated for I2C communication. For legacy purposes these constants aren't removed.

Button

void buttonCallback(func_t callbackFunction = NULL);

// call a function when the shield button is pressed
void buttonClick(void)
{
    // ...
}
buttonCallback(buttonClick);

// to unregister just call the same function without the callback function
buttonCallback(NULL);

Registers a callback function for when the shield button is clicked, it is connected to the pin 7 on the shield. It defaults to a falling edge interrupt as the pin is pulled high by the micro-controller internal pull-up resistor when the button is released.

Calling this function sets the pin mode as input and the value to logical 1 to activate the internal pull-up resistor (between 20 and 50K) needed to define the logical state when the button is not pressed. Pressing the button shorts the line to ground via a 10K external short-circuit protection resistor in case one configures the pin as output and presses the button. This effectively makes a voltage divider and the actual voltage when pressed is about 1V, the micro-controller data sheet stipulates that a low input level is detected at 0.3*Vcc which is 1.5V at 5V.

Note: mind the contact bounce which can be annoying, but preventable.

Timed functions

Sometimes it's useful to call a function regularly, such as to check a sensor every 10 seconds or follow a line while checking for obstacles every 500ms. A timed function lets the user set up an automatic call to a function at predetermined intervals.

The time interval is a multiple of 100ms.

int8_t setTimer(func_t callbackFunction, uint16_t interval, uint8_t callNumber = 0);

// call a function every 5*100ms = 500ms, 10 times
void myFunction(void)
{
    // ... this code must be executed in under 100ms
}
setTimer(myFunction, 5, 10);

// call a function every 600*100ms = 60 seconds = 1 minute, indefinitely
void myFunction2(void)
{
    // ...
}
setTimer(myFunction2, 600);

This function uses the Timer/Counter 1, the same as the servo function, so the servo motors cannot be used while this is being used.

As the delay between the calls (interval) is coded on a 16-bit unsigned integer the maximum time between calls can be at most 2^16ms = 65536ms = 65.536s, so a little over a minute.

The function can be called at most 256 times if the callNumber parameter is provided, otherwise it will be called indefinitely.

To unset a timed function use void unsetTimer(uint8_t);, setTimer() returns an identification number that can be used to unset it later.

// set and then unset a timed function
void myFunction3(void)
{
    // ...
}
uint8_t myTimedFunctionID = setTimer(myFunction3, 10);

unsetTimer(myTimedFunctionID);

If the timed function slots are full setTimer() will return a -1, the maximum number of timed functions can be set in the prismino.h file with the TIMEDFUNCTIONS definition which is by default set to 4.

NOTE: the way the program calls the functions requires all of the timed functions combined to take less than 100ms in execution time, so avoid delay() functions inside of your routine calls and only use the setTimer() for small code bits.

Miscellaneous functions

Sound

void play(uint16_t frequency, uint16_t time);

// play a 440Hz sound during 1 second
play(440, 1000);

Sends a square wave to the Robopoly shield's buzzer (pin 8) to output a sound. The parameters are the frequency in Hz and the play-time in milliseconds.

It's actually a macro to the Arduino tone() function, it defines the buzzer pin so only 2 arguments are needed.

Definitions

These shortcuts, that are included in the library, can be used to make the code more clean:

Servo pins

The numbers correspond to the markings on the PCB silkscreen.

#define S1 6 // PD7
#define S2 5 // PC6

DIP switch pins

Do not use these pins as outputs! The reason for this convoluted order is because they were easier to route on the PCB this way.

#define DIP1 0 // PD2
#define DIP2 1 // PD3
#define DIP3 3 // PD1
#define DIP4 2 // PD0

Button pin

This pin is protected with a 10K resistor against shortcuts when it's set as output and the button is clicked (shorted to ground).

#define BTN 7 // PE6

Buzzer pin

There's a 1K resistor in line with the buzzer to limit the current.

#define BZR 8 // PB4

LED pin

There's a 1K resistor in line to limit the LED current, when LEDs on the shield and PRismino are installed the equivalent resistance is 0.5K.

#define LED 13 // PC7

Potentiometer pin

The potentiometer has a 10K resistor in line with the pin, this serves as a short-circuit protection in case this pin is used as output and the potentiometer is set to the opposite voltage.

#define POT A0 // PF7

Examples

A few example programs are also provided to show how to use these functions and all the components on the Robopoly Shield. See them under File -> Examples -> PRismino in Arduino IDE.

Version log

1.5 (2015-04-05)

1.4 (2014-10-12)

1.3 (2014-04-23)

1.2 (2014-03-14)

1.1 (2014-02-17)

1.0 (2013-10-26)

Licence

This software is published under LGPL.