Code examples

Basic sketch for making a useless machine

Use the code in the folder on the right. Instead of using the build in servo library we use a custom library where you can also control speed and also make it wait until it has positioned itself in the right position.

Syntax:

servoArm.set([position], [speed]);

The first parameter is the position of the servo. You can set the position to anything between 0 and 180.

The second parameter is the speed. It is the amount of delay the servo should make for each degree it moves. E.g 5 is fast and 40 is really slow. 20 seems to be a good value.

You can also decide to wait until the servo has come into position.

servoArm.set([position], [speed]);

servoArm.wait();

Then the code will pause until the position you give it is the same position the servo is in.

So to animate the arm you can write:

servoArm.set(130, 50);

servoArm.wait();

servoArm.set(100, 10);

servoArm.wait();

servoArm.set(140, 10);

Download the code from the folder above.

Let us see what the sketch does

On the left you can see an explanation of what each line does in the sketch. This is for you to get an idea of how the code is constructed.

At first it seems rather complex, but if you return to this explanation you will slowly get ownership of the code and the differnet components.

You do not need to know everything about the code. The most important part is to figure out how you can add small pieces of code into the code to make it behave differently.


This includes the servoSmartLib

#include "servoSmartLib.h"

This defines the servo object for the servo arm.

ServoSmart servoArm;

These are variables that holds the current the last state of the button. It is neccesary so we can see if anything has changed.

boolean btnState = false;

boolean btnStateLast = false;

The setup is a function that is run once. It setups the servo, the button pin and the serial communication to the computer. In the end it sends a "Starting" message to the computer.

void setup() {

servoArm.setup(4);


pinMode(5, INPUT_PULLUP);

Serial.begin(9600);

Serial.println("Starting");

}

The loop function is where the interaction is happening. The loop function runs constantly.

void loop() {

Below are are the commands inside the loop.

The first command is a reading what state the button is in (is it turned on or off)

btnState = !digitalRead(5);

Then the state of the button is compared to the last state. If the state has change this means that somebody did something. Read more about state and events here.

if (btnStateLast != btnState)

{

If the button has been changed to on (true) then the servo arm is moved to position 137 at speed 10. E.g. moving up to press the button.

if (btnState == true)

{

//move to press the button

servoArm.set(137, 10);

}

Else if the button has been changed to off the servo arm is moved to position 60 at speed 10 e.g. moving back into the box.

else if (btnState == false)

{

// hide in my cave

servoArm.set(60, 10);

}

}

The last thing to do is to save the current state in the last state variable so when the code loops it can be compared again.

btnStateLast = btnState;

This call is just so the servo library can update the position and move it slowly over time. Not something you have to worry about. It just need to be there.

servoArm.update();

Finally the loop function is ended with a curly bracket

}

Make different modes depending on how many times the button has been pressed

#include "servoSmartLib.h"


float dist = 0;

ServoSmart servoArm;

boolean btnState = false;

boolean btnStateLast = false;

int counter = 0;


void setup() {

servoArm.setup(4);

pinMode(5, INPUT_PULLUP);

Serial.begin(9600);

Serial.println("Starting");

}



void loop() {

btnState = !digitalRead(5);


//Serial.println(millis());


if (btnStateLast != btnState) // the button has changed

{


if (btnState == true) // the button has been pressed

{

//move to press the button

Serial.println("button pressed");

counter = counter + 1;

Serial.println(counter);

if(counter >0 && counter <2) // first slow mode

{

servoArm.set(140, 20);

}

else if(counter >= 2 ) // aggressive mode

{

servoArm.set(140, 5);

}

}

else if (btnState == false) // robot has pressede the button

{

// hide in my cave

servoArm.set(60, 20);

Serial.println("button back");

}

delay(4);

}

btnStateLast = btnState;

servoArm.update();

}

React dynamically based on how fast you press the button

#include "servoSmartLib.h"


float dist = 0;

ServoSmart servoArm;

boolean btnState = false;

boolean btnStateLast = false;


unsigned long lastButtonChangeTimer = 0;


void setup() {

servoArm.setup(4);

pinMode(5, INPUT_PULLUP);

Serial.begin(9600);

Serial.println("Starting");

}



void loop() {

btnState = !digitalRead(5);


//Serial.println(millis());


if (btnStateLast != btnState) // the button has changed

{


if (btnState == true) // the button has been pressed

{

//move to press the button

Serial.println("button pressed");

int timePassed = millis() - lastButtonChangeTimer;

int armSpeed = map(timePassed,0,10000,0,50);

armSpeed = constrain(armSpeed, 0, 50);

Serial.println(armSpeed);

servoArm.set(140, armSpeed);

}

else if (btnState == false) // robot has pressede the button

{

lastButtonChangeTimer = millis();

// hide in my cave

servoArm.set(60, 20);

Serial.println("button back");

}

delay(4);

}

btnStateLast = btnState;

servoArm.update();

}

Explanation of components in your kit

See more under the arduino input and output.

The sensor shield

The sensor shield is a shield which makes it easy to connect sensors and components to the Arduino without having to solder.

Here is how it works. The numbers indicate the pin number that the pin connects to to the Arduino. Notice the GVS written on the vertical. This indicates what each pin does:

  • S is the signal pin.

  • V are 5v (also called plus)

  • G are ground (also called minus).

The section with the pins starting with an A are analog pins that can read a digital value and an analog value.

IR distance: Sensing the distance from an object

The infrared distance sensor uses infrared pulses to measure the distance from the sensor and to whatever is in front of it. This can be used in setups where a certain output is comes from being closer or further away from the sensor. (Note that the sensors will usually look like the ones from the picture, and not from the diagram).

Connect power to 5v, ground to ground and output to analog pin 0.

In order to test if the sensor is working, use the following code:

void setup() {

Serial.begin(9600);

}

void loop() {

Serial.println(analogRead(A0));

}


Analog read and serial print are functions that allow you to view the input directly in the serial monitor. Read more about it here.

Switch button

A button is a simple way to create interaction. It can be used to create different outputs depending on the length of the push, the amount of pushes, etc.

Attach one wire from the button to a digital pin (in the example we have used digital pin 3), and the other to ground. To test the circuit, use the following code:

void setup() {

pinMode(5, INPUT_PULLUP);

Serial.begin(9600);

}

void loop() {

boolean btnPressed = !digitalRead(5);

if(btnPressed == true) {

Serial.println("button is pressed down.");

}

}

Signal (yellow in the diagram) is the orange wire on a servo motor. Ground is brown and red is 5V (always in the middle). Make sure to turn the connector correctly or nothing will happen.

Verify that you have the tap servoSmartLib.h

Servo

A servo is a motor with gears and shafts which can be controlled. Depending on the input they are given, they can turn to specific positions within 180 degrees.

The Servo is connected with ground to ground, power to 5v and middle pin to a digital pin (in this example, pin 9).

This code works for the normal servo within a 180 degree spectrum, and makes it rotate to the middle position:

This is with the servoSmartLib (use the sketch from the useless machine example and change the kode to the following):

#include "servoSmartLib.h"

ServoSmart servoArm;


void setup() {


servoArm.setup(4);


pinMode(5, INPUT_PULLUP);

Serial.begin(9600);

Serial.println("Starting");

}


void loop() {

servoArm.set(120, 6);

servoArm.update();

}


This is with the build in servo libary:

#include <Servo.h>

Servo myservo;

void setup() {

myservo.attach(4);

}

void loop() {

myservo.write(90);

}

Control neopixels

Neopixels are versatile light strings where each diode can be controlled individually. Each one has Red, Green, and Blue and can be from 0 to 255 in brightness. Multiple libraries exists to use noepixels. We suggest you use fastled.

Add the library: "menu->sketch->include library->manage libraries"

Search for "fastled" and click install

Code

Neopixels are a simple way to make colorful and dynamic interactions.

Connect ground to ground, power to 3v and DIN (digital input) to a digital pin (in this example we use digital pin 3). Make sure that the direction of the strip is correct (as seen in diagram).

Include the library "FastLED" by Daniel Garcia.

To test the neopixels, use the following code which will make the first three pixels light up:

#include "FastLED.h"
#define NUM_LEDS 10
#define DATA_PIN 2

CRGB leds[NUM_LEDS];

void setup()
{

FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

}

void loop()
{

leds[0]= CRGB( 255, 0, 0);

leds[1]= CRGB( 0, 255, 0);

leds[2]= CRGB( 0, 0, 255);

FastLED.show();

}

This example will turn all the leds red

#include "FastLED.h"


// How many leds in your strip?

#define NUM_LEDS 10

#define DATA_PIN 2



// Define the array of leds

CRGB leds[NUM_LEDS];


void setup() {

FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

}


void loop() {


for (int i = 0; i < NUM_LEDS; i = i + 1)

{

leds[i] = CRGB( 255, 0, 0);

}

FastLED.show();


}

This example makes a chase

#include "FastLED.h"


// How many leds in your strip?

#define NUM_LEDS 10

#define DATA_PIN 2



// Define the array of leds

CRGB leds[NUM_LEDS];


void setup() {

FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

Serial.begin(9600);

}

int numLedsOn = 0;

void loop() {


for (int i = 0; i < NUM_LEDS; i = i + 1)

{

if (i < numLedsOn)

{

leds[i] = CRGB( 255, 0, 0);

}

else

{

leds[i] = CRGB( 0, 0, 0);

}

}


FastLED.show();

numLedsOn = numLedsOn + 1;

if (numLedsOn == NUM_LEDS)

{

numLedsOn = 0;

}

Serial.println(numLedsOn);


delay(100);


}

Touch sensor

Include the library ”ADCTouch” by Alexander Pruss. Same way as with the neopixels library above. Use the code to view the values in the serial monitor.


#include <ADCTouchSensor.h>

ADCTouchSensor touch0 = ADCTouchSensor(A0, -1);


void setup() {

Serial.begin(9600);

touch0.begin();

}

void loop() {

float value0 = touch0.read();

Serial.println(value0);

}

Combining your components

Distance sensor + Neopixels

The code to the right uses an if statement to detect if something is in front of the ir distance sensor and changes the neopixels to a color.

#include "FastLED.h"

#define NUM_LEDS 10

#define DATA_PIN 2

CRGB leds[NUM_LEDS];

int irPin = A0;


void setup()

{

FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

Serial.begin(9600);

}

void loop()

{

Serial.println(analogRead(irPin));


if (analogRead(irPin) < 200)

{

leds[0] = CRGB( 7, 245, 201);

leds[1] = CRGB( 7, 245, 201);

leds[2] = CRGB( 7, 245, 201);

}

else

{

leds[0] = CRGB( 0, 0, 0);

leds[1] = CRGB( 0, 0, 0);

leds[2] = CRGB( 0, 0, 0);

}

FastLED.show();

}

Button + neopixels

This example connects the button (input) to the neopixels (output).

#include "FastLED.h"


// How many leds in your strip?

#define NUM_LEDS 10

#define DATA_PIN 2



// Define the array of leds

CRGB leds[NUM_LEDS];


void setup() {

FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

pinMode(11, INPUT_PULLUP);

}


void loop() {


boolean btnPressed = !digitalRead(11);

if (btnPressed == true)

{

leds[0] = CRGB( 255, 0, 0);

leds[1] = CRGB( 0, 255, 0);

leds[2] = CRGB( 0, 0, 255);

}

else

{

leds[0] = CRGB( 0, 0, 0);

leds[1] = CRGB( 0, 0, 0);

leds[2] = CRGB( 0, 0, 0);


}

FastLED.show();


}


Timing without delay

Using delay is bad practice because it halts everything on the board. Instead use "millis()". This example does something every two seconds:

unsigned long timer = 0;

void setup()

{


}


void loop()

{

if(millis()-timer > 2000) // do something every two seconds)

{

timer = millis();

//do something here

}

}

Detecting a button event

The above button example only indicate the current state (on/off or pressed/not pressed). If does not detect the actual event of something happening. An event is when something changes from one state to another. E.g. you want to do something when the button was released => Going from a pressed state to a not pressed state. This requires us to "remember" the old state an compare it to detect the change.

boolean buttonState = false;

boolean buttonStateOld = false;


void setup() {

pinMode(5, INPUT_PULLUP);

Serial.begin(9600);

}


void loop() {

buttonStateOld = buttonState;

buttonState = digitalRead(5);


if (buttonState != buttonStateOld) {

Serial.println("Button has changed");

if (buttonState == LOW)

{

Serial.println("It was pressed");

}

}

}


The button example above detect what state the button is in. It will repeatedly write button pressed to the serial prompt.

To detect when a button as has gone from one state to another we need to compare the old state with the new state.

Map function

The mapping function is used to map som range to another range. E.g. your distance sensor runs from 0-1024 and your neopixel colors runs from 0-255. Then you can make mape to convert the scale.

In the example on the left the ir distance sensor date is converted in to (roughly) mm.

https://www.arduino.cc/reference/en/language/functions/math/map/


void setup() {

// put your setup code here, to run once:

Serial.begin(9600);

}


void loop() {

// put your main code here, to run repeatedly:

int distMM = map(analogRead(A0),630,130,50,380);

Serial.println(distMM);

delay(10);

}

Blink without delay


#include "FastLED.h"

#define NUM_LEDS 10

#define DATA_PIN 11

unsigned long timer = 0;


boolean turnOn = false;


CRGB leds[NUM_LEDS];


void setup()

{


FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);


}


void loop()

{

if (millis() - timer > 2000) // do something every two seconds)

{


timer = millis();


//do something here

turnOn = !turnOn;

}


if(turnOn == true)

{

leds[0] = CRGB( 255, 0, 0);

}

else

{

leds[0] = CRGB( 0, 0, 0);

}


FastLED.show();

}

#include "servoSmartLib.h"


float dist = 0;

ServoSmart servoArm;


boolean btnState = false;

boolean btnStateLast = false;



void setup() {


servoArm.setup(4);


pinMode(5, INPUT_PULLUP);

Serial.begin(9600);

Serial.println("Starting");

}



void loop() {

if(analogRead(A0))

{

servoArm.set(80, 10);

}

else

{

servoArm.set(100, 10);

}

servoArm.update();


}

MAke it annoyed WHEN pressed 8 times

#include "servoSmartLib.h"


float dist = 0;

ServoSmart servoArm;


boolean btnState = false;

boolean btnStateLast = false;

int numPressed = 0;



void setup() {


servoArm.setup(4);


pinMode(5, INPUT_PULLUP);

Serial.begin(9600);

Serial.println("Starting");

}



void loop() {

btnState = !digitalRead(5);

//https://www.arduino.cc/en/Tutorial/StateChangeDetection

if (btnStateLast != btnState) // the button has changed

{

if (btnState == true) // the button has been pressed

{

//move to press the button

servoArm.set(137, 10);

numPressed = numPressed +1;

Serial.println("button pressed");

Serial.println(numPressed);

}

else if (btnState == false)

{

// hide in my cave

servoArm.set(60, 10);

Serial.println("button back");

}


}


if(numPressed == 8)

{

servoArm.setWait(random(70,130), 10);

}


btnStateLast = btnState;

servoArm.update();



}


#include "servoSmartLib.h"


float dist = 0;

ServoSmart servoArm;


boolean btnState = false;

boolean btnStateLast = false;

int numPressed = 0;

#include "FastLED.h"

#define NUM_LEDS 10

#define DATA_PIN 11

CRGB leds[NUM_LEDS];


void setup() {


servoArm.setup(4);

FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);


pinMode(5, INPUT_PULLUP);

Serial.begin(9600);

Serial.println("Starting");

}



void loop() {

btnState = !digitalRead(5);

//https://www.arduino.cc/en/Tutorial/StateChangeDetection

if (btnStateLast != btnState) // the button has changed

{

if (btnState == true) // the button has been pressed

{

//move to press the button

servoArm.set(137, 10);

numPressed = numPressed +1;

Serial.println("button pressed");

Serial.println(numPressed);

}

else if (btnState == false)

{

// hide in my cave

servoArm.set(60, 10);

Serial.println("button back");

}


}




btnStateLast = btnState;

servoArm.update();


leds[0]= CRGB( 255, 0, 0);

leds[1]= CRGB( 0, 255, 0);

leds[2]= CRGB( 0, 0, 255);

FastLED.show();



}


#include "servoSmartLib.h"


float dist = 0;

ServoSmart servoArm;


boolean btnState = false;

boolean btnStateLast = false;

int numPressed = 0;

#include "FastLED.h"

#define NUM_LEDS 10

#define DATA_PIN 11

CRGB leds[NUM_LEDS];


void setup() {


servoArm.setup(4);

FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);


pinMode(5, INPUT_PULLUP);

Serial.begin(9600);

Serial.println("Starting");

}



void loop() {

btnState = !digitalRead(5);

//https://www.arduino.cc/en/Tutorial/StateChangeDetection

if (btnStateLast != btnState) // the button has changed

{

if (btnState == true) // the button has been pressed

{

//move to press the button

servoArm.set(137, 10);

numPressed = numPressed +1;

Serial.println("button pressed");

Serial.println(numPressed);

}

else if (btnState == false)

{

// hide in my cave

servoArm.set(60, 10);

Serial.println("button back");

}


}




btnStateLast = btnState;

servoArm.update();



Serial.println(analogRead(A0));


if (analogRead(A0) < 200)

{

leds[0] = CRGB( 7, 245, 201);

leds[1] = CRGB( 7, 245, 201);

leds[2] = CRGB( 7, 245, 201);

}

else

{

leds[0] = CRGB( 0, 0, 0);

leds[1] = CRGB( 0, 0, 0);

leds[2] = CRGB( 0, 0, 0);

}

FastLED.show();


}