![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhXaUNRePPPZyiCf3xWRQiphUC53UUYydD4zhfL_0pnf-fOLZvIQ_OR-MmgMkMk0LO9NiwYbr21XC1NomuMh5Zen0hD55LiOef1Kai48s0DvIYFMTaRzl4J4r_yyKdCOOAyaYSOCdrMRsa6/s320/Kuva_1mp.jpg) |
Sauvat alussa parkissa |
|
Tämän
ohjelman nimi kertoo (sattumalta), että tässä ohjataan kahta
servoa ”samanaikaisesti”. Tuo määrittely lainausmerkeissä,
sillä samanaikaisuus on näennäistä, koska aliohjelma on yhteinen
molemmille, toisen pitää ehtiä kääntymään paikalleen, ennen
kuin naapuri saa lähteä liikkeelle. Servo-objektin nimenä on nyt
Taulu. Tässä ei määrittelyissä kytketä tuota nimeä
kirjasto-ohjelmalle (#include <Servo.h>; Servo Taulu;
Taulu.attach(pinni), vaan ohjauksen aliohjelmassa, koska
kummallakin servolla on oma ja eri ohjauspinninsä.
Tämä
sovellus ulottuu vielä Suomen itsenäisyyttäkin varhaisempaan
aikaan. Onneksi ei sentään syntynyt savumerkkejä, vaan tällainen
kirjaintaulu, missä kahden varren risteyskohdalla voidaan
”kirjoittaa langattomasti”; kunhan vain näköyhteys on voimassa.
Aikoinaan tällaisia oli käytössä viesti-ihmisillä lippujen ja
valojen lisäksi.
Ohjelman
käynnistyessä varret menevät odottamaan ”parkkipaikalle”.
Käynnistyspainikkeen painaminen saa varret kääntymään
vaakasuoraan (START) hetkeksi ja aloittamaan sen jälkeen
merkkien poiminnan. Sanojen välillä varret myöskin viivähtävät
parkissa. Kun sanottava on tullut kerrotuksi, hymyilee laite
itselleen.
Sanomaa
en tuo tässä esiin. Se on helpoiten nähtävissä YouTube-videosta.
Google ei ole erityisen innokas haeskelemaan näitä minun
videoitani, joten helpoiten ne löytyvät avaamalla YouTube ja
kopioimalla videon osoite hakuriville (antinarduvideo45.yotube.com).
Sieltä ne ponnahtavat tarjolle aiemmatkin pätkät.
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn1dgr6X7FOl7e_4v1MFgSSOUCHtJ7BBqjd_rQXlDynRql8qlwDHpg6YdguTImiDT5HSw0Lph2_ZtvuPRTVvnD5OhckbAlNZyLqf10-PkmAemkmydu8bvxmx4gF0KfbQqhxW1Llk_G5GfR/s320/Kuva_2mp.jpg) |
Lopussa on hyvä hymyillä! |
|
Pienoismallien
ohjauksen lisäksi servoille on paljonkin käyttöä. Twitterissä
huomasin jokin aika sitten hauskan idean: automaattinen roskiksen
kansi. Siinä oli Arduinoon liitetty liiketunnistin, ja kun käsi
lähestyi, painoi servo jalkakytkintä ja avasi kannen. Ja tietysti
sulki sen jälkeen, kun käsi poistui tunnistealueelta. Kahdella
servolla voisi tehdä vaikkapa piirturin. Toinen servo piirtää
paperille ja toinen nykii paperia eteenpäin.
Ohjelmallisesti
tässä ei; tuon dynaamisen kirjasto-ohjelmamäärittelyn lisäksi
ole mitään erityistä. Pohdin sitä, että olisiko ollut järkevää
viiveet suorittaa aliohjelmassa, mutta en nähnyt sen juurikaan
typistävän ohjelman mittaa. Tässä ajastuksen perustana on
sisäisen kellon käsky (millis();). Jokaisella
ohjelmakierroksella luetaan sen hetkinen arvo. Jos se on saavuttanut
seuraavan aikaportaan (Int_AikaEro = 100;), hypätään
viiveen aliohjemaan, missä asetetaan seuraava aikaporras (ero on
aina 100 millisekuntia) ja asetetaan todeksi boolean muuttuja
(Bol_Aika = true;). Tällä vähennetään viivelaskureita
sekvenssin askelissa. Pääohjelman lopussa asetetaan tämä
tilabitti nollaksi (Bol_Aika = false;).
OHJELMA
45
/*******************************
*
Ohjelma 45
*
25.08.2017
*
Kahden servon ohjaus
********************************/
#include
<Servo.h> // Servon kirjasto-ohjelma
Servo
Taulu; // Kehittää servo-objektin
int
kulma = 0;
const
int
Con_ServoOikea = 8;
const
int
Con_ServoVasen = 9;
const
int
Con_Start = 10;
boolean
Bol_Start = false;
const
int
Con_TestLED = 13;
//
Kirjaintaulukot
int
Arr_Vas[14] = {41,61,71,77,26,45,55,65,16,34,45,55,2,93};
int
Arr_Oik[14] = {9,11,18,35,20,26,37,56,30,37,48,63,80,0};
//
Kellon määrittelyt:
unsigned
long Ulo_MilliSek = 0;
int
Int_AikaEro = 100;
unsigned
long Ulo_UusiMilliSek = Int_AikaEro;
boolean
Bol_Aika = false;
//
Ohjausseqvenssi
int
Seq_Servo = 1;
const
int
Con_MerkkiVali = Int_AikaEro/5;
int
Int_MerkkiVali = Con_MerkkiVali;
const
int
Con_SanaVali = Int_AikaEro * 15;
int
Int_SanaVali = Con_SanaVali;
const
int
Con_SARTviive = Int_AikaEro/5;
int
Int_STARTviive = Con_SARTviive;
int
Int_MerkkiViive = Int_AikaEro * 3;
//
Aliojelmat
void
Fun_Ohjaus( int
kulma){
Taulu.attach(Con_ServoOikea);
Taulu.write(Arr_Oik[kulma]);
delay(400);
Taulu.attach(Con_ServoVasen);
Taulu.write(Arr_Vas[kulma]);
delay(400);
}//
Ohjauksen funktion loppu
void
Fun_Viive(){
Ulo_UusiMilliSek = Ulo_UusiMilliSek +
Int_AikaEro;
Bol_Aika
= true;
}//
Viive-funktion loppu
//Asetukset
void
setup() {
Serial.begin(9600);
pinMode(Con_Start, INPUT);
}//
Asetusten loppu
//PÄÄOHJELMA
void
loop() {
//
Kellotus:
Ulo_MilliSek
= millis();
if(Ulo_MilliSek >=
Ulo_UusiMilliSek){
Fun_Viive();}
//
Käynnistyskytkimen luku
Bol_Start
= digitalRead(Con_Start);
//
Servojen ohjaussekvenssi
switch
(Seq_Servo) {
case
1: // Alkuasento PPP
Fun_Ohjaus(12);
delay (Int_SanaVali);
Seq_Servo
= 2;
break ;
case
2: // Starttipainike
if (Bol_Start
== true){Seq_Servo = 3;}
break ;
case
3: // Ohjaus Starttiin
Fun_Ohjaus(13);
delay (Int_AikaEro * 2);
Seq_Servo
= 4;
break ;
case
4: // Viipyminen Startissa
if (Bol_Aika
== true){ Int_STARTviive--; }
if (Int_STARTviive == 0){
Int_STARTviive = Con_SARTviive;
Seq_Servo
= 5;}
break ;
case
5:
Fun_Ohjaus(8);
delay (Int_MerkkiViive);
Seq_Servo
= 6;
break ;
case
6:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 7;}
break ;
case
7:
Fun_Ohjaus(10);
delay (Int_MerkkiViive);
Seq_Servo
= 8;
break ;
case
8:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 9;}
break ;
case
9:
Fun_Ohjaus(3);
delay (Int_MerkkiViive);
Seq_Servo
= 10;
break ;
case
10:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 11;}
break ;
case
11:
Fun_Ohjaus(10);
delay(Int_MerkkiViive);
Seq_Servo
= 12;
break ;
case
12:
Fun_Ohjaus(12);
delay (Int_SanaVali);
Seq_Servo
= 13;
break ;
case
13:
Fun_Ohjaus(5);
delay (Int_MerkkiViive);
Seq_Servo
= 14;
break ;
case
14:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 15;}
break ;
case
15:
Fun_Ohjaus(4);
delay (Int_MerkkiViive);
Seq_Servo
= 16;
break ;
case
16:
Fun_Ohjaus(12);
delay (Int_SanaVali);
Seq_Servo
= 17;
break ;
case
17:
Fun_Ohjaus(7);
delay (Int_MerkkiViive);
Seq_Servo
= 18;
break ;
case
18:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 19;}
break ;
case
19:
Fun_Ohjaus(1);
delay (Int_MerkkiViive);
Seq_Servo
= 20;
break ;
case
20:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 21;}
break ;
case
21:
Fun_Ohjaus(6);
delay (Int_MerkkiViive);
Seq_Servo
= 22;
break ;
case
22:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 23;}
break ;
case
23:
Fun_Ohjaus(9);
delay (Int_MerkkiViive);
Seq_Servo
= 24;
break ;
case
24:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 25;}
break ;
case
25:
Fun_Ohjaus(5);
delay (Int_MerkkiViive);
Seq_Servo
= 26;
break ;
case
26:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 27;}
break ;
case
27:
Fun_Ohjaus(7);
delay (Int_MerkkiViive);
Seq_Servo
= 28;
break ;
case
28:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 29;}
break ;
case
29:
Fun_Ohjaus(1);
delay (Int_MerkkiViive);
Seq_Servo
= 30;
break ;
case
30:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 31;}
break ;
case
31:
Fun_Ohjaus(3);
delay (Int_MerkkiViive);
Seq_Servo
= 32;
break ;
case
32:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 33;}
break ;
case
33:
Fun_Ohjaus(0);
delay (Int_MerkkiViive);
Seq_Servo
= 34;
break ;
case
34:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 35;}
break ;
case
35:
Fun_Ohjaus(2);
delay (Int_MerkkiViive);
Seq_Servo
= 36;
break ;
case
36:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 37;}
break ;
case
37:
Fun_Ohjaus(5);
delay (Int_MerkkiViive);
Seq_Servo
= 38;
break ;
case
38:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 39;}
break ;
case
39:
Fun_Ohjaus(6);
delay (Int_MerkkiViive);
Seq_Servo
= 40;
break ;
case
40:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 41;}
break ;
case
41:
Fun_Ohjaus(11);
delay (Int_MerkkiViive);
Seq_Servo
= 42;
break ;
case
42:
if (Bol_Aika
== true){ Int_MerkkiVali--; }
if (Int_MerkkiVali == 0){
Int_MerkkiVali = Con_MerkkiVali;
Seq_Servo
= 43;}
break ;
case
43: // Uusi startti
if (Bol_Start
== true){Seq_Servo = 1;}
break;
}//
Ohjaussekvenssi loppu
Bol_Aika
= false;
delay(1);
}//Pääohjelma
Loppu