V dnešním článku se podíváme, jak může robot používat nárazníky. Ty ve skutečnosti nejsou nic jiného, než dva dráty, které vycházejí na obě strany na přední straně robota. Vypadají a fungují velice podobně, jako fousky koček – pokud robot najede na nějakou překážku, ta ohne drát, čímž se sepne obvod jako u vypínače a robot tak detekuje překážku.
Nárazníky jsou součástí kitu SparkFun Inventor’s Kit for RedBot. Ve standardní sadě SparkFun Inventor’s Kit for RedBot je bohužel nenajdete.
K tomu, abychom mohli na nárazy do překážek reagovat, musíme se naučit v programu říci „když se stane toto, udělej toto“. K tomu v programovacích jazycích slouží takzvané „podmínky“. Díky nim můžeme robota naučit zajímavé kousky. S podmínkami jsme se již setkali, ale nevěnovali jsme jim moc pozornosti. Nejjednodušší z nich je podmínka if().
Podívejme se teď na příklad, který naleznete v RedBot příkladech: File > Examples > SparkFun RedBot Library > Exp5_Bumpers. Tento kód nahrajeme do RedBota.
/*********************************************************************** * Exp5_Bumpers -- RedBot Experiment 5 * * Now let's experiment with the whisker bumpers. These super-simple switches * let you detect a collision before it really happens- the whisker will * bump something before your robot crashes into it. * * This sketch was written by SparkFun Electronics, with lots of help from * the Arduino community. * This code is completely free for any use. * Visit https://learn.sparkfun.com/tutorials/redbot-inventors-kit-guide * for SIK information. * * 8 Oct 2013 M. Hord * Revised 30 Oct 2014 B. Huang ***********************************************************************/ #include <RedBot.h> RedBotMotors motors; RedBotBumper lBumper = RedBotBumper(3); // initialzes bumper object on pin 3 RedBotBumper rBumper = RedBotBumper(11); // initialzes bumper object on pin 11 int buttonPin = 12; // variable to store the button Pin int lBumperState; // state variable to store the bumper value int rBumperState; // state variable to store the bumper value void setup() { // nothing here. } void loop() { motors.drive(255); lBumperState = lBumper.read(); // default INPUT state is HIGH, it is LOW when bumped rBumperState = rBumper.read(); // default INPUT state is HIGH, it is LOW when bumped if (lBumperState == LOW) // left side is bumped/ { reverse(); // backs up turnRight(); // turns } if (rBumperState == LOW) // right side is bumped/ { reverse(); // backs up turnLeft(); // turns } } // reverse() function -- backs up at full power void reverse() { motors.drive(-255); delay(500); motors.brake(); delay(100); // short delay to let robot fully stop } // turnRight() function -- turns RedBot to the Right void turnRight() { motors.leftMotor(-150); // spin CCW motors.rightMotor(-150); // spin CCW delay(500); motors.brake(); delay(100); // short delay to let robot fully stop } // turnRight() function -- turns RedBot to the Left void turnLeft() { motors.leftMotor(+150); // spin CW motors.rightMotor(+150); // spin CW delay(500); motors.brake(); delay(100); // short delay to let robot fully stop }
Co by se mělo stát
Po spuštění programu by se měl robot začít pohybovat dopředu, dokud jeden z nárazníků nenarazí na překážku. Pokud jako první narazí levá strana, měl by robot popojet dozadu a otočit se doprava. Pokud poprvé narazí pravá strana, robot couvne a otočí se doleva.
Můžete upravit časování ve funkcích reverse(), turnRight() a turnLeft(), abyste dosáhli požadovaného posunu dozadu a otočení o 90° po každém nárazu.
Důležité části kódu
Nad funkcí setup() jsme si vytvořili dva objekty nárazníků pomocí třídy RedBotBumper. Konstruktor potřebuje jeden parametr, a to pin, na kterém je nárazník připojen.
RedBotBumper lBumper = RedBotBumper(3); // initialzes bumper object on pin 3 RedBotBumper rBumper = RedBotBumper(11); // initialzes bumper object on pin 11
Konstruktor RedBotBumper() automaticky nastaví vybrané piny jako vstupy s interním pull-up rezistorem. To mimo jiné znamená, že pokud je nárazník neaktivní, je výchozí stav vstupu HIGH. Více o vstupech s interním pull-up rezistorem si můžete přečíst ve článku Funkce input-pullup.
Stav nárazníku je možné získat pomocí metod lBumper.read() a rBumper.read(). Když dojde k nárazu do nárazníku, dotkne se drát šroubu připojeného ke GND, což způsobí změnu hodnoty na LOW. V příkladu je také vidět použití proměnných, které uchovávají stav jednotlivých nárazníků.
lBumperState = lBumper.read(); // default INPUT state is HIGH, it is LOW when bumped rBumperState = rBumper.read(); // default INPUT state is HIGH, it is LOW when bumped
Naučte se více – podmínky
Chcete se dozvědět více o logice v podmínkách? Jedna z věcí, které vám při programování pro Arduino robota RedBot přijdou vhod, je tvorba složitých podmínek, založených na různých vstupech a senzorech.
Logické hodnoty
Jsou možné jenom dvě logické hodnoty – true (pravda) a false (nepravda). Všechny logické výrazy i operace jsou vyhodnoceny buď jako true, nebo jako false. Pokud podmínka if() dostane hodnotu true, provede se, pokud ne, neprovede se. Tedy úplně nejjednodušší podmínky jsou:
if(true){ //... } if(false){ //... }
To ale většinou v praxi nevyužijeme a budeme chtít trochu komplexnější chování. K tomu slouží právě logické výrazy.
Logické výrazy
Podmínky se v programovacích jazycích tvoří pomocí tzv. logických výrazů. Ty mohou obsahovat logické operace a také porovnání. Logické výrazy mohou být seskupeny pomocí závorek – například (A == B). Logické operace a operace porovnání jsou:
Symbol | Co operátor zkoumá | Výsledná logická hodnota |
A == B | Je a rovno b? | true, pokud jsou A a B stejné, jinak false |
A != B | Je a různé od b? | true, pokud jsou A a B různé, jinak false |
A > B | Je a větší než b? | true, pokud je A větší než B, jinak false |
A < B | Je a menší než b? | true, pokud je A menší než B, jinak false |
A >= B | Je a větší nebo rovno b? | true, pokud je A větší nebo rovno B, jinak false |
A <= B | Je a menší nebo rovno b? | true, pokud je A menší nebo rovno B, jinak false |
if(A == B){ //... } if(A != B){ //... } if(A > B){ //... } if(A < B){ //... } if(A >= B){ //... } if(A <= B){ //... }
Logické operace
Pomocí logických operací můžeme skládat dohromady logické výrazy a dosáhnout tak i velice komplexního chování. Můžeme tak například zkoumat platnost i více výrazů najednou a různě je kombinovat.
Symbol | Jméno operace | Description |
X && Y | AND – logické a | (výraz X) && (výraz Y) je true, pokud X i Y jsou true, jinak false |
X || Y | OR – logické nebo | (výraz X) || (výraz Y) je true, pokud alespoň jeden z výrazů X a Y je true, jinak false |
!X | NOT – logická negace | !(výraz X) je true, pokud je výraz X false, jinak false |
X | Y | X && Y |
false | false | false |
false | true | false |
true | false | false |
true | true | true |
X | Y | X || Y |
false | false | false |
false | true | true |
true | false | true |
true | true | true |
X | !X |
false | true |
true | false |
Například tedy můžeme vytvořit složenou podmínku:
if (mod == 1 && (teplota < hodnota || prepis == true)){ digitalWrite(topeni, HIGH); }
Tato podmínka spustí topení, pokud je mod rovno 1 a zároveň platí, že je teplota pod určitou hodnotou, nebo je hodnota prepis rovna true.
Další úpravy
Možná jste si všimli, že program neobsahuje možnost, že RedBot narazí oběma „fousky“ současně. Zkuste tuto možnost přidat a zajistěte, že se robot v tomto případě otočí o 180°.