Start Elkretssimulator


Struktur

Minimalt program

void setup()
{
   // det som skall köras vid start
}

void loop()
{
  // denna programloop körs i all
  // evighet, dvs så länge strömmen
  // är påslagen
}

En bra grej veta från start, för att underlätta inlärning, det är hur du fixar utskrifter så att du kan exprimentera och få återkoppling på det du gör. För att skriva ut något måste du sätta upp den seriella monitorn. Därefter kan du göra utskrifter och se resultatet i den seriella monitorn. Du hittar den seriella monitorn under verktyg/seriell monitor.

void setup()
{
  Serial.begin(9600);
  Serial.println("Nu har jag initierat seriella monitorn");
}

void loop()
{
  Serial.println("Detta skrivs ut varje sekund.");
  delay(1000);
}

Om du kör ovan program så ser det ut såhär i monitorn.



#include

Om du vill importera extern kod så använder du #include. I denna externa kod kan ligga funktioner du vill använda dig av. Ta t.ex. exemplet där du styr ett servo med arduino. Genom att inkludera Servo.h så får du enkla funktioner med vars hjälp du kan kontrollera servots rörelser.
#include <Servo.h>

#define SERVO_PIN 9
#define POT_PIN 1

Servo myservo;  // skapar myservo -objekt

int analog_signal;
int vinkel;

void setup() 
{
  myservo.attach(SERVO_PIN);
}

void loop() 
{
  analog_signal = analogRead(POT_PIN);
  vinkel = map(analog_signal, 0, 1023, 0, 180);
  myservo.write(vinkel);     // vrid servo vinkel
  delay(20);   // ge servot chansen flytta sig
}

#define

Detta direktiv substituerar (ersätter) något i din kod med något annat. Nedan kod gör att du kan använda orden SANT och FALSKT iställer för true och false.
#define SANT true
#define FALSKT false

/* kommentarer */

Detta har du kanske redan sett i kod du tittat på. Man kan på olika sätt lägga in kommentarer i koden för att beskriva koden. Dessa kommentarer gör ingenting i koden. För att kompilatorn skall veta att det är kommentarer måste man omge dem med vissa tecken eller inleda med vissa tecken. Exempel följer:
// Detta är en kort kommentar
// jag kan fortsätta på nästa rad, varje ny rad
// måste inledas med //

/* Man kan också skriva
kommenterer så här med en
inledande teckenkombination och
på slutet av kommentaren har vi
en avslutande teckenkombination */


; (semikolon)

Varje programsats avslutas alltid med ett semikolon. Mycket viktigt, annars blir det fel!

Datatyper

bool och boolean

Bool är alltså true eller false. Standarden i språket är bool, men arduino vill gärna att vi använder icke-standarden boolean.

bool aktiv = true;
bool running = false;
bool connected = true;
boolean arduino = true;

byte

8 bitar unsigned, dvs från 0 till 255
byte litet_tal = 255;
byte port1 = 128;

int

En int är 2 bytes och har som standard tecken, dvs värden från -32,768 till 32,767. Ett litet unsigned framför så representerar det istället värden från 0 till 65535.

int x = -2000;
unsigned int = 45000;

word

Detta är samma sak som unsigned int. Dvs 2 bytes och representerar värde från 0 till 65535.
word siffra = 23000;

short

En short är alltid 2 bytes, dvs samma som int. På avancerade processorer är int ibland mer än 2 bytes och då kan short användas när en "stor" int icke behövs.

char

char tecken = 'A';
char tecken = 65;

unsigned char

Samma som byte, representerar 0-255.

long

En long är 4 bytes och kan representera värden mellan -2,147,483,648 to 2,147,483,647. En unsigned long kan representera 0 till 4,294,967,295 dvs 2^32 - 1.

float

Detta är ett flyttal. De lagras som 4 bytes men kalkyleras internt lite annorlunda än tidigare datatyper. Istället lagras talet som flyttal med 6-7 värdesiffror samt 10-potens.
float pi = 3.14159;
float diameter = 7.5;
float omkrets = pi * diameter;

double

Detta float fast lagras med 8 bytes istället för 4 vilket ger en mycket högre precision, alltså fler värdesiffror.
double pi = 3.141592654;
double diameter = 7.5786;
double omkrets = pi * diameter;

array

int myInts[6];
int myPins[] = {2, 4, 8, 3, 6};
int mySensVals[6] = {2, 4, -8, 3, 2};
char message[6] = "hello";

String - Strängar

char* myStrings[]={"String 1", "String 2", 
"String 3", "String 4", "String 5","String 6"};

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  for (int i = 0; i < 6; i++)
  {
    Serial.println(myStrings[i]);
    delay(500);
  }
}

String()

Det finns en del klasser/objekt i språket, t.ex. String. Du kan skapa en String och sedan finns som vanligt (för dig som är bekant med C++) ett gäng funktioner du kan använda på denna string.
String str = "Hejsan varlden!";
String str2 =  String('a');
String str3 =  String("This is a string");
String str4 =  String(stringApa + " with more");
String str =  String(13);
String str =  String(analogRead(0), DEC);
Du kan sedan använda t.ex. följande funktioner på dessa strängar
str.charAt(unsigned int n) - tecknet på position n i str
str.compareTo(String str) - jämför str med str2, 0 om samma
str.c_str() - konvertera str till en C-sträng
str.endsWith(String s2) - true om str avslutas med s2
str.equals(String str2) - true om str samma som str2
str.equalsIgnoreCase(String str2) - som ovan + ignorecase
str.getBytes(byte [] buf, len) - kopiera str till buf
str.indexOf(String substr) - ger index om substr del av str
str.lastIndexOf(String substr) - som ovan med senaste förekomsten
str.length() - ger längden på str
str.replace(String ersatt, String med) - ersätter ersatt med med
str.setCharAt(index, c) - ersätter tecknet på position index
str.startsWith(String str2) - true om str startar med str2
str.substring(from, to) - ge substring av str
str.toCharArray(char [] buf, len) - kopiera till buffer
str.toLowerCase() - returnerar strängen i gemener
str.toUpperCase() - returnerar strängen i VERSALER
str.trim() - tar bort inledande och avslutande space

void

Betyder noll och ingen datatyp och används t.ex. framför funktioner som inte returnerar någonting.
void setup()
{
  // ...
}

void loop()
{
  // ...
}

Typkonvertering

Om du har en variabel av en typ men vill få in värdet i en variabel av en annan typ, så kan du i vissa fall typkonvertera. Detta görs enkelt genom att skriva typen du önskar och omge det du vill konvertera med parenteser.
int portvarde_int = 128;
byte portvarde_byte = byte(portvarde_int);
char portvarde_char = char(portvarde_byte);
long portvarde_long = long(portvarde_int);
word portvarde_word = word(portvarde_int);

Artitmetik

Multiplikation (*), division (/), addition (+) och substraktion (-) är väl ganska givna. Likaså har väl de flesta kommit kontakt med tilldelningsoperatorn (=).
int antal = 10;

Betyder alltså att vi tilldelar variabeln antal siffran 10.
int antal = 10 + 7; // antal är nu 17
antal = antal - 2;  // antal är nu 15
antal = antal * 2;  // antal är nu 30
antal = antal / 10; // antal är nu 3

En mer krånglig operator är modulo -operatorn. Denna ger resten efter en division mellan 2 tal.
int rest = 10%5;  // rest bli 0 eftersom 10/5 går jämt upp
int rest = 7%5;  //  5 går en gång i 7 och 2 blir rest
int rest = antal%2;  // rest blir 1 om antal är ett udda tal

Jämförelse

Det finns naturligtvis ett gäng jämförelsemöjligheter. Mindre än och större än.
6 < 8 // sant
8 < 8 // falskt  (mindre än)
8 <= 8 // sant (mindre än eller lika med)
6 > 8 // falskt (större än)
8 >= 8 // sant (större än eller lika med)
8 == 8 // sant (lika med)
8 == 7 // falskt (lika med)
8 != 8 // falskt (inte lika med)
8 != 7 // sant (inte lika med)

Logiska operatorer

Tre viktiga logiska operatorer hålla reda på. Det är && som betyder och, det är || som betyder eller samt ! som betyder inte.
bool jordenRund = true;
bool solenVarm = true;
bool marsVarm = false;

bool pastaende1 = jordenRund && solenVarm;
bool pastaende2 = marsVarm && solenVarm;
bool pastaende3 = !marsVarm && solenVarm;
bool pastaende4 = marsVarm || solenVarm;
Vilka av ovan påstående är sanna? Nummer 1 är sant, därför att jordenRund är sant och solenVarm är sant. Påstående nummer 2 är falskt, där att båda är inte sanna. Påstående nummer 3 är sant, därför att vi har satt ett ! (som betyder inte) framför marsVarm. Slutligen är påstående 4 sant därför att det räcker att den ena av de 2 är sanna då det står ett eller i mitten.

Bitvis operator

& (bitvis och)

Skriv med ett enkelt &. Båda parametrar måste vara sanna för att svaret skall bli sant.

  1010
& 0111
--------
= 0010

I siffror är detta 10&7=2

Observera att denna operation alltså "rensar" alla positioner du önskar, genom att du kan ta ett värde och ett annat där du placerat nollor överallt där du vill rensa.. Om du inte observerat detta, titta noga så att du begriper denna finess en gång för alla.

  0010000011000000
| 1111111100000000
------------------
= 0010000000000000

| (bitvis eller)

Skriv med ett enkelt |. Räcker att den ena är sann för att svaret skall bli sant.

  0010
& 0110
--------
= 0110

I siffror är detta 2|6=6

Observera att denna operation alltså "sätter" en önskad bit på en viss position. Om du inte observerat detta, titta noga så att du begriper denna finess en gång för alla.

  0010000011000000
| 0000000000001000
------------------
= 0010000011001000

~ (bitvis icke)

Denna operator inverterar värdet, dvs 0 blir 1 och 1 blir 0.

 ~00001010
----------
= 11110101

I siffror är detta ~6=245. Observera att eftersom denna operator inverterar nollor som står framför talet vi angivit blir svaret beroende på vilket datatyp vi använder, dels hur många bitar datatypen är på men också om det har ett tecken (signed) eller inte (unsigned).

^ (bitvis xor)

Denna operator fungerar som or/eller -operatorn fast med tillägget att om båda parametrar är 1 så blir svaret 0.

  00001010
^ 11001100
----------
= 11000110

I siffror 10^204=198.

<< (bitshift left/vänster)

Bitshift vänster innebär att bitarna skiftas åt vänster så många positioner som parametern anger. Om du skifter fler positioner än talet representerar så går värdet förlorat.

byte a = 5;        // binärt: 00000101
byte b = a << 3;   // binärt: 00101000

>> (bitshift right/höger)

Bitshift vänster innebär att bitarna skiftas åt höger så många positioner som parametern anger. Om du skifter fler positioner än talet representerar så går värdet förlorat.

byte a = 40;       // binärt: 00101000
byte b = a >> 3;   // binärt: 00000101,

Sammansatta operatorer

Konceptet med sammansamma operatorer är helt enkelt att förkorta sättet att skriva. Det är t.ex. väldigt vanligt att man ökar ett värde med t.ex. 1. Eller minskar ett värde med 1. Man skriver då.
i = i + 1;
j = j - 1;
Detta kan man skriva på det kortare sättet.
i++;
j--;
Man kan använda det kortare sätter för att öka eller minska mer än 1. Vi kan öka med 5 eller minska med 17.
i+=5;  // samma som i = i +5;
j-=17;   // samma som j = j - 17;
Vi kan också använda detta för multiplikation eller division.
i/=2;  // samma som i = i / 2;
j*=3;   // samma som j = j * 3;

Konceptet kan också användas för de bitvisa operatorerna.
a &=6; // samma som a = a&6;
b ^= 7; // samma som b = b^7;
pvalue |= 1; // samma som pvalue = pvalue | 1;

Nu när vi kommit så här långt med vår förståelse; ett litet övningsexempel! Om du sneglat på lite kod för att initiera interruptet på arduino har du stött på följande kod. Vad är det som händer här?

TCCR1B |= (1 << CS12) | (1 << CS10);
CS12 och CS10 är makron för bitpositionerna, där 0 är första positionen och 1 andra, 2 tredje osv. I include -filen för atmega328 kan man hitta dessa.

#define CS10 0
#define CS11 1
#define CS12 2
#define WGM12 3
#define WGM13 4
#define ICES1 6
#define ICNC1 7

Det står alltså egentligen.
TCCR1B |= (1 << 2) | (1 << 0);

Dvs (1 << 2) skapar först värdet

  100

Och (1 << 0) skapar värdet

  001

Vi tar dem båda eller varandra.

  100
| 001
-----
  101

Sen tar vi värdet i registret TCCR1B, vad det nu är, och så sätter vi helt enkelt dessa bitar, dvs bit 2 och 0. Om värdet i TCCR1B var 0 från början.

  00000000
| 00000101
----------
  00000101

Detta värde sätter registret TCCR1B till. (När vi sätter bit 2 och 0 får vi en prescaler=1024 i vårt timerinterrupt)

Pekare

En pekare pekar på värdet av en annan variabel. Poängen med pekare är just att man kan ändra själva pekaren., stega upp eller ner pekaren, så att denna pekare pekar på andra variabler. När vi skapar en array av heltal eller tecken, så är det egentligen en pekar-konstruktion som vi sätter upp (fast med en lite enklare syntax), där array'ens index läggs till adressen där matrisen startar. Nog om det nu.

2 verktyg behöver vi här. Dels en referens-operator (&) för att få adressen till en variabel så att vi kan sätta pekaren. Dels en dereferens-operator (*) för att läsa vad pekaren pekar på.

byte p = 128;
char c = 'h';
int i = 55;
byte b = 8;
byte *ptr = &p;

Pekaren ptr pekar nu på det adressutrymmet där p ligger. Om vi vill skriva ut värdet av pekaren så skriver vi *p får att få värdet av det pekaren pekar på, dvs 128.

Kontrollstruktur


if ()

Vad if gör är att ställa frågan om någonting är sant. Om det är sant, då utförs det som följer inom klammer { ... }. Om falskt så händer ingenting.
bool sant = true;
int temperatur = 26;

if(sant)
{
  sant = false;
}

if(temperatur > 25)
{
  // svettas
}

if () else

Ibland vill man att något alternativ skall urföras ifall en fråga inte är sann och här kommer else in i bilden. Else utförs om frågan inte är sann.
int temperatur = 26;

if(temperatur > 25)
{
  // svettas
}
else
{
  // okej temperatur
}

while ()

Ibland vill man att något skall upprepas sålänge något är sant. While utför det inom klammer i en evig loop sålänge uttrycket bakom while är sant.
bool fortsatt_snurra_vanster = true;

while(fortsatt_snurra_vanster)
{
  // snurra lite åt vänster
}

do ... while ()

En liten omkrivning skapar en while -loop som utförs minst en gång. Om du tittar på ovanstående while -loop så är det inte garanterat att den utförs överhuvudtaget. Om det såg ut såhär hade ingenting hänt:
bool fortsatt_snurra_vanster = false;

while(fortsatt_snurra_vanster)
{
  // snurra lite åt vänster
}

Men ibland vill man ha en konstruktion som görs minst en gång.
bool svar_saknas = true;

do
{
  // ställ en fråga

  // om svar har givits sätt svar_saknas = false;

} while(svar_saknas)
Ovan ställer en fråga och upprepar denna fråga tills ett svar har givits.

for(... ; ... ; ...)

Denna konstruktion skapar en loop. Det finns 3 stycken fack här. I det första sätter man ett startvärde. I den andra villkoret för att fortsätta och i den tredje vad som skall hända efter att ett varv är avslutat.
int raknare;
int summa = 0;

for(raknare = 0; raknare < 10; raknare++)
{
  summa = summa + raknare;
}
Ovan snurra kommer räkna ut vad 1+2+3+4+5+6+7+8+9 blir och detta hamnar i variabeln summa.

switch...case


int alternativ = 2;

switch (alternativ) 
{
    case 1:
      // alternativ = 1 ... gör någonting
      break;

    case 2:
      // alternativ = 2 ... gör någonting
      break;

    case 3:
      // alternativ = 3 ... gör någonting
      break;

    default:
      // om inget alternativ matchar
      // så görs detta istället
      break;
}

break

Detta är ett nyckelord som kan användas i olika sammanhang för att avbryta något. Som t.ex. i switch -satsen ovan. Men kan även användas i en for -loop.
for (x = 0; x < 255; x ++)
{
  if(stoppa_loopen)
    break;	
}
Funkar även i while -loopar.
while(fortsatt_snurra_vanster)
{
  if(nöd_stopp)
    break;	

  // snurra lite åt vänster
}

continue

int raknare;
int summa = 0;

for(raknare = 0; raknare < 10; raknare++)
{
  if(raknare = 5)
    continue;

  summa = summa + raknare;
}
Ovan snurra kommer hoppa över värdet 5 och räkna ut vad 1+2+3+4+6+7+8+9 blir och detta hamnar i variabeln summa.

Funktioner

Det är viktigt förstå funktioner då detta är nödvändigt för att få struktur på större program, att dela upp koden i vettiga funktioner. Det finns också en hel del inbyggda funktioner, bl.a. för att läsa in & ut -signaler, vilket du ser i nästa avslutande sektioner.
En funktion döps precis som en variabel till något med bokstäver a-z (inga svenska bokstäver). Även siffror fungerar, men första tecknet måste vara en bokstav. Efter funktionen följer en parentes med de variabler funktionen anropas med.
void initieraMinKrets(int varde)
{
  // gör något
}

void Setup()
{
   initieraMinKrets(10);
}
Ovan kommer alltså när programmet startas att anropa initieraMinKrets med värdet 10. Om man vill returnera ett värde från en funktion anger man returvärdets datatyp först.

float pi = 3.1415926;
float radie = 5;
float area;
float omkrets;

float cirkelnsOmkrets(float diameter)
{
  return diameter * pi;
}

float cirkelnsArea(float radie)
{
  return pi * radie * radie;
}

void Setup()
{
   omkrets = cirkelnsOmkrets(radie + radie);
   area = cirkelnsArea(radie);
}


Digital In och Ut

pinMode(int pin, int mode)

Innan en pinne kan användas som in eller ut -pinne måste den definieras, vilket görs med pinMode. T.ex. pinMode(0, OUTPUT) sätter pinne 0 till en output -pinne. De olika tänkbara modes är INPUT, OUTPUT eller INPUT_PULLUP. Den sista gör samma jobb som när man monterar ett pullup-motstånd på ingången. Detta kan behövas om källan t.ex. har en open-collector utgång.

void Setup()
{
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
}


digitalWrite(int pin, int val)

Skriver digitalt värde val (HIGH eller LOW) på pinne pin. Exempelvis skriver digitalWrite(0, HIGH) en hög signal på pinne 0. Nedan exempel både på digitalWrite samt pinMode från exemplet med 7-segmentdisplay.

#define _HIGH HIGH
#define _LOW LOW

// pinnar för segmenten a,b,c,d,e,f,g
int segPins[8] = {2,3,4,5,6,7,8,9};    
 
// pinne för gemensam anod/katod
int commonPin = 10;

// siffra som skall visas
int num = 7;

int segLEDs[11][7]=
{
{1,1,1,1,1,1,0},
{0,1,1,0,0,0,0},
{1,1,0,1,1,0,1},
{1,1,1,1,0,0,1},
{0,1,1,0,0,1,1},
{1,0,1,1,0,1,1},
{1,0,1,1,1,1,1},
{1,1,1,0,0,0,0},
{1,1,1,1,1,1,1},
{1,1,1,0,0,1,1},
{0,0,0,0,0,0,0}
};

void setup()
{  
  for (int i=0; i<8;i++)
    pinMode(segPins[i],OUTPUT);
    
  pinMode(commonPin,OUTPUT);   
  digitalWrite(commonPin, _LOW);
    
  clear();
  digit(num);
}

void loop() // används inte
{
}

void digit(int num)
{  
  for (int i=0; i<7; i++)
    digitalWrite(segPins[i],segLEDs[num][i]?_HIGH:_LOW);
}

void clear()
{
  for (int i=0; i<7; i++)
    digitalWrite(segPins[i],_LOW);       
}

digitalRead(int pin)

Läser digitalt värde från en pinne och ger svaret HIGH or LOW vilket fördefinierade heltal (int). T.ex. digitalRead(4) läser värdet från pinne 4. Om pinnen inte är kopplad till något blir svaret slumpmässigt. Nedan exempel läser värdet på pinne 2 och om något tryckt på knappen så ska den göra något.

#define RELEASE HIGH
#define PUSH LOW

volatile int btn = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);
}

void loop()
{
  btn=digitalRead(2); 
  Serial.println(btn);
  if(btn==PUSH)
  {
    // gör något
  }
  delay(1000);
}

Analog In och Ut

analogRead(int pin)

Denna funktion läser det analoga värdet från en analog ingång. Värde man får är ett värde mellan 0-1023. T.ex. läser analogRead(2) det analoga värdet från pinne 2. Exemplet nedan läser analog signal på pinne 3 och skriver ut på consolen.

int val = 0;

void setup() 
{
  Serial.begin(115200); 
}

void loop() 
{
  val = analogRead(3);
  Serial.println(val);  
}



analogWrite(int pin, int value)

Skapar en pulsbreddsmodulerad signal på pinne pin, med en viss duty cycle där 0 är 0 och 255 är 100%. Nedan från exempel där vi skapar en analog utsignal på en analog pinne, vilket kräver ett litet RC -filter.

int pwmPin = 3;
int analogInputPin = 3;
int val = 0;

void setup()
{
  pinMode(pwmPin, OUTPUT);
}

void loop()
{
  // vi läser det analoga värdet från potentimetern
  // kopplad som spänningsdelare. Får ett värde mellan
  // 0 och 1023.
  val = analogRead(analogInputPin);  

  // Vi skriver detta värde dividerat med 4 på pwmPin
  // eftersom pwmPin tar ett värde från 0 till 255
  analogWrite(pwmPin, val / 4);
}

Mer exempel. Om man ansluter en logikanalysator till arduinon och kör följande program, så får man nedanstående utdata på logikanalysatorn.

void setup() 
{
  analogWrite(6,250);   // Gul port 6
  analogWrite(5,128);   // Grön port 5
  analogWrite(10,64);   // Blå port 10
  analogWrite(9,10);    // Lila port 9
}

void loop() 
{

}


Gul duty cycle = 250/255 = ca 98%
Grön duty cycle = 128 / 255 = ca 50%
Blå duty cycle = 64/255 = ca 25%
Lila duty cycle = 10 / 255= ca 3.9%

Om du tittar noga ovan ser du att det är olika frekvenser för pinne 9 & 10 (ca 490 Hz) än vad det är för 5 & 6 (ca 980 Hz). Det är helt i sin ordning eftersom det är 2 olika prescaler som styr frekvensen här. Prescaler för 9 & 10 är 32768 vilket ger 490 Hz (16 MHz klockfrekvens / 32768 = ca 490) och för pinne 5 & 6 halva detta värde.

Det går att ändra frekvenser här genom att ändra prescaler. Det är register TCCR0B för pinne 5 & 6, TCCR1B för pinne 9 & 10, TCCR2B för pinne 3 & 11.


Mäta pulslängder

pulseIn(int pin, int value, unsigned long timeout)

Returnerar det antal sekunder pulsen är HIGH (eller LOW) på en viss pinne. Value kan vara HIGH eller LOW och timeout är den tid vi ger funktionen. Efter denna tid returnerar funktionen utan svar. Nedan exempel från vår avståndsmätare med sonic sensor.

// Sensorns pinnar
const int triggerPin = 3;
const int echoPin = 4;

long timeMicroseconds;
float dist_cm;

void setup()
{
  Serial.begin(9600);  
  pinMode(triggerPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop()
{
  digitalWrite(triggerPin, LOW);
  delayMicroseconds(2);
  digitalWrite(triggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(triggerPin, LOW);

  timeMicroseconds = pulseIn(echoPin, HIGH);
  dist_cm = (float)timeMicroseconds * 0.034 / 2;

  Serial.print(dist_cm);
  Serial.println(" cm");

  delay(100);
}

pulseInLong(...)

Den sublima skillnaden mot ovan verkar vara att denna funktion, när den anropas, om signalen redan är HIGH så väntar den tills signalen blir LOW och därefter HIGH innan den börjar mäta.

Generera fyrkantvåg

tone(int pin, unsigned int frequency)

Genererar en fyrkantsvåg (med duty cycle 50%) på pinne pin med en viss frekvens, eventuellt under en viss tid duration i millisekunder, då är anropet tone(int pin, unsigned int frequency, unsigned int duration).

noTone(int pin)

Stänger av ovanstående fyrkantvåg på pinne pin om en sådan är skapad.

Läsa och skriva Seriella data

byte b = shiftIn(int dataPin, int clockPin, bitOrder)

Funktionen läser in en byte i taget från en serieström av data på dataPin. För varje bit går klocksignalen hög, nästa bit läses och klockan går låg. Du anger en dataPin (data pinne) och en clockPin (klocksignal), bitOrder kan sedan vara MSBFIRST (mest signifikant först) eller LSBFIRST (minst signifikant först).

shiftOut(int dataPin, int clockPin, bitOrder, byte value)

Den omvända versionen av shiftIn som istället skriver ut en byte i taget i den bitordning som är angiven av bitOrder. En ny bit skrivs samtidigt som klocksignalen går från låg till hög och åter till låg.

Tid

delay(int milliseconds)

Delay väntar det antal millisekunder (tusendels sekunder) man anger. T.ex. delay(500) väntar en halv sekund.

delayMicroseconds(unsigned int microseconds)

delayMicroseconds gör samma sak som delay, fast väntar det antal mikrosekunder (miljontedels sekunder) man angivit.

micros()

Lämnar ifrån sig antal passerade mikrosekunden sedan arduino startade. Räknaren börjar om efter ca 70 minuter när det blir overflow.

millis()

Lämnar ifrån sig antal passerade millisekunder sedan arduino startade. Räknaren börjar om efter ca 50 dagar när det blir overflow.


Matematik

abs(x)

Ger ifrån sig absolutbeloppet av x. Dvs, absolutbeloppet av 5 är 5. Absolutbeloppet av -4 är 4. Dvs, ett eventuellt tecken kommer plockas bort.

constrain(x, a, b)

Returnerar x om x ligger mellan a och b. Om x är mindre än a, så returneras a, om x är större än b så returneras b.

map(value, fromLow, fromHigh, toLow, toHigh)

map projicerar ett värde value som har en värdemängd från fromLow till fromHigh på en ny värdemängd i intervallet toLow till toHigh. Exempel nedan från hur man styr ett servo med arduino. Vi läser ett analog värde 0-1023 och behöver ett värde 0 till 180 som är vinkeln som skall in i myservo.

#include <Servo.h>

#define SERVO_PIN 9
#define POT_PIN 1

Servo myservo;  // skapar myservo -objekt

int analog_signal;
int vinkel;

void setup() 
{
  myservo.attach(SERVO_PIN);
}

void loop() 
{
  analog_signal = analogRead(POT_PIN);
  vinkel = map(analog_signal, 0, 1023, 0, 180);
  myservo.write(vinkel);     // vrid servo vinkel
  delay(20);   // ge servot chansen flytta sig
}

max(x, y)

Returnerar det största värdet av x och y.

min(x, y)

Returnerar det minsta värdet av x och y.

pow(float base, float exponent)

Ger ifrån sig base upphöjt till exponent. pow(2,3) ger alltså ifrån sig 8.

sq(double x)

Returnerar kvadraten av ett tal x, dvs talet multiplicerat med sig själv. Dvs sq(9) = 81.

sqrt(double x)

Returnerar roten ur x. Dvs sqrt(81) = 9.


Trigonometri

cos(float x)

Ger ifrån sin cosinusvärdet av x radianer.

sin(float x)

Ger ifrån sin sinusvärdet av x radianer.

tan(float x)

Ger ifrån sig tangensvärdet av x radianer.

Testa för Bokstäver & Siffror

isAlpha(char c)

Ger ifrån sig true eller false beroende på om c är en bokstav eller inte. isAlpha testar alltså om en viss char är bokstav.

isAlphaNumeric(char c)

Ger ifrån sig true eller false beroende på om c är en bokstav eller en siffra eller inte. isAlphaNumeric testar alltså om en viss char är bokstav eller siffra.

isAscii(char c)

Returnerar true eller false beroende på om c är en ASCII -char.

isControl(char c)

Returnerar true eller false beroende på om c är en ett kontrolltecken.

isDigit(char c)

Returnerar true eller false beroende på om c är en siffra.

isGraph(char c)

Returnerar true eller false beroende på om c är något synligt tecken (space, mellanrum, är t.ex. ett tecken men det syns inte).

isHexadecimalDigit(char c)

Returnerar true eller false beroende på om c är ett hexadecimalt tecken, dvs antingen 0-9 eller A-F.

isLowerCase(char c)

Returnerar true eller false beroende på om c är gemener (små bokstäver).

isPrintable(char c)

Returnerar true eller false beroende på om c är möjlig skriva ut.

isPunct(char c)

Returnerar true eller false beroende på om c är en punkt. Till punkt räknas punkt, kommatecken och semikolon, exlamation, m.fl punkter).

isSpace(char c)

Returnerar true eller false beroende på om c är space eller inte.

isUpperCase(char c)

Returnerar true eller false beroende på om c är VERSALER (STORA BOKSTÄVER).

isWhitespace(char c)

Returnerar true eller false beroende på om c är ett whitespace, dvs; space, formfeed ('\f'), newline ('\n'), return ('\r'), horisontal tab ('\t'), and vertikal tab ('\v')).

Slumptal

random(max)

Kan även anropas med random(min, max) och ger alltså ett slumtalsvärde mellan min och max eller mellan o och max.

randomSeed()

Denna funktion initialiserar random -funktionen och skall normalt anropas innan random anropas första gången. Detta för att få unika slumptalsserier.


Bits and Bytes

bit(bit)

Räknar ut värdet av en bit. Dvs bit 0 är 1, bit 1 är 2, bit 2 är 4, bit 3 är 8 osv.

bitClear(x, n)

Skriver 0 på bit-position n i värdet x, där första positionen är 0, andra är 1 osv.

bitSet(x, n)

Skriver 1 på bit-position n i värdet x, där första positionen är 0, andra är 1 osv.

bitRead(x, n)

Returnerar bitvärdet (0 eller 1) på position n i talet x.

bitWrite(x, n, b)

Fungerar som bitSet fast du kan välja själv om 0 eller 1 skall skrivas, vilket du anger som b.

byte b = highByte(word x)

Word är här 16 bitar, dvs 2 bytes vardera på 8 bitar. Returnerar den höga halvan (byte) av x.

byte b = lowByte(word x)

Returnerar den låga halvan av x.


Externa Interrupt

attachInterrupt(pin, ISR, mode)

Kopplar en pinne till en interruptfunktion. Mode kan här vara något av följande:

LOW triggar ISR interruptet när pinnen är låg
CHANGE triggar ISR när pinnens värde skiftar.
RISING triggar ISR skiftar från LOW till HIGH.
FALLING triggar ISR skiftar från HIGH till LOW.

På Due, Zero och MKR1000 fungerar även HIGH, vilket är motsatsen till LOW ovan.

I nedan exempel är en knapp kopplad till pinne 0 och koden är tänkt att analysera knappstuds/kontaktstuds, dvs räkna hur många tillslag det egentligen blir.

volatile int antal_knapptryck = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);  
  attachInterrupt(0, knapptryck, FALLING);
}

void loop()
{
  Serial.println(antal_knapptryck);
  delay(1000);
}

void knapptryck()
{
  antal_knapptryck++;
}

detachInterrupt()

Stänger av ovanstående interrupt. På arduino Due kan man även ange pinne, dvs detachInterrupt(pin).


Interrupt

interrupts()

Slår på alla interrupt.

noInterrupts()

Stänger av alla interrupt.