Monday, September 28, 2009

Videogames, part II

So.. Number 2 on my list of annoyances in videogames (in no particular order). Superfluous Press whichever Button! This actually stopped me from playing through the greatest videogame in the history of man kind (in fact, the history of the universe, judging by it's diciples); Metal Gear Solid 2. The number of keypresses required just to be able to move an arthritis-ridden, stooping, smoking old geezer around the screen proved too much for me. I did not even finish the first level. It went straight to Gamestop, where I could at least recuperate some of my money. So much the better that the gamestudios never see a dime of that extra value generated from the second hand market. It is my one and only way of letting them know that I do not appreciate them wasting my time. By the way, MGS2 is by no means the only one, it just happends to be the worst one I've experienced so far. The post isn't about MGS2 in particular, but about consolegames in general.

First, there's just about 600.000 logos, pictures og god knows what, god knows why, and videos. This all invariably results in vigorous keypresses, on just about any key there is on the controller. I've also resorted to picking up any other controllers connected to the console in question, just in case there's a bug. To no avail, ofcourse. Who, in their right mind, thinks that I care who made the soundengine?? Or, more accurately, who thinks that I care about it so much, that I will find this information interesting, not only before I play the game for the first time, but every single time I play it?? This can not wait untill the credits roll?? This, I think, can be likened to prominently, for 15 minutes, dispaying the name of the gaffer before every movie shown. (No, I don't know what a 'gaffer' is either. But I know every movie have one.)

Then there's the "Press Start". Ok... Well, I've spent some time considering this, and I've come to the conclusion that it might be excusable, in the event that the game console has more than one controller attached. If not, NOOOOOOOOO! Get it? Just no. We, as a species, have placed people on the moon. The Cell-processor is, as far as I'm concerned, the grestest feat since the Alpha-processor, with a straight lineage to the wheel. It's a marvel. A testimony to human ingenuity. Yet, there it is, all nicely tucked into a sleek black console in my "study". (That's what my wife calls the room where she puts all of my stuff.) So don't tell me we can't make a videogame that doesn't require me to tell it that I want to play. It's on. That means I want to play it.

Well, so I've accepted the Press Start.. For now. So now what? Well, now comes, if you're lucky, the "Please select a storage device". Hm. I only have the one, so I guess I'll choose that one. What would any reasonable intelligent being guess, if pushed? There you go. Gamestudios are entirely staffed by an alien race, come to this planet in order to subdue us all into a mindless dance of pressing buttons, for no apparent reason. They, meanwhile, will probably ravage the women we ignore while in front of our consoles. Meh.. The game, by the way, needs to know which storage device to use every time it is started..

"Please select storage device" is only acceptable if there is more than one storage device! And only, only the first time the game is started. How hard can this be??

Well, that's three (or many). Time to play! Nope. First, they feel the need to inform you that this particular game has a cutting edge feature. One feature so new, so inventive, so revolutionary, that reminding you of it every time you start the game is entirely justified. Nay, required, even. Nevermind that you've logged in the better part of your toddlers life playing the game, nevermind that you've started the game far more times than you've called your mother in your entire life. No, the task they perform, and what you need to acknowledge with a keypress, is that of saving your progress. And it is of vital importance that you do not, I repeat not, under any circumstance, within the timespan of 2 ms take a dive towards your gameconsole and yank the out powercable. Good to know.

Then theres the Main Menu. Dear Lord.. I don't even know where to begin with that one. I've started games on my console literally thousands of times. I do not own thousands of games. That leads to the inevitable conclusion, again if you are a reasonable human being, that I continue where I left off far more times than I start a new game. In short, the number of keypresses from I start the console with a gamedisk in it untill I'm exploding slugs with a flamethrower should be Nil. If you insist, I can settle for one. "Do you want to continue where you left off [Yes][No]". That would be sensible. That would make me happy.

There's more keypresses. Sooo many more. But I think I've made my point. Superflous keypresses are bad.

Videogames, and how they annoy me!

Given the previous topics on the blog, it should come as no surprise that I own videogame consoles. Several, in fact. Xbox360, a PS3, and even a PSP. I don't have any games for that one, I simply like the fact that it will, if I should feel so inclined, allow me connect it to the PS3 and play wichever game is running on the PS3, on the PSP. I can not for the life of me see how that could ever be even remotely practial, but I do like the geek-factor. Yes, I suppose I am a geek.

What is perhaps a bit more surpising, given my apparent interests, is that I am married. To a woman. Who's not a geek. I am married to a real, live, non-geeky woman, who cares about non-geeky stuff. Such as what colour things are. If I should phone home one day with news of a recent purchase of, say, a car, her first response would be "oh, god..". This would be muttered. I would not, at this time, offer up more information, as "oh god" is not a question, and the muttering does not invite to share my excitement about said purchase. So there would, very likely, be Awkward Silence. The very next response would in all likelyhood be "what colour is it?"

I think this is a key difference between men and women, the properties of objects which they care about. (This, and the ability to laugh at Monty Python. Ofcourse, I am stereotyping here, but I am allowed to. It's my blog, and the Internets are well suited for this sort of thing. ) Now, speaking for myself, I would not inquire about the colour of anything unless this information would be of importance in actually locating this thing. I would, for instance, ask about the colour of my wifes new car if I had never seen it before, and was looking for it. Me, and most men I know, would rather inquire about things like horsepower, the number of doors, engine size and fuel, properties which concern the utility of whichever object is in question. Women seem to favour estethics. Nothing wrong with that, I like things that look good, but I can't help feeling that any object you bring into your existence should serve some purpose.

This also extends to the topic of the post, videogames. I don't know where to begin.. Most videogames annoy me to an extent hardly experienced by mankind before. The level of annoyance in Stalin when Hitler crossed the border into mother Russia, for instance, would be relatively minor in comparison. I quite often ask myself what these people are thinking of. So I think I shall start a list, right here, of Stupid Stuff to do in videogames. Lets start with cutscenes.

Cutscenes, for the uninitiated, are the short movieclips between gameplay. Some times they are there to convey information of importance to the gameplay, but most of the time it's there, as far as I can work out, for two reasons: 1) To show off how good they are at making things look exciting, and (far worse) 2) to fill up the time with nonsens so they can say "20 hours of gameplay", when there is in fact 2 hours of gameplay and 18 hours of mindless drivel.

I have in my flat the following devices which will let me watch moving pictures: 4 laptops. 1 PS3. 1 Xbox360. 1 PSP. 2 TV's. 1 DVDplayer. 1 PVR. Any one of these devices will show me movies and TV 24/7. So why, my dear game-studio exec, do you think I purchase a $60 game? To watch movies? The answer, as the more perceptive of you may suspect, is no.

Are all gamestudio exec's failed Hollywood directors? Are they like the security-guards on the subway, who failed to get in to police academy or the army, and now has to settle for some low-end job? Are they constantly thinking about that fantastic movie-deal they'll get, just as soon as they're discovered, by someone who buys videogames to watch movies?

Cut-scenes annoy me. The only thing that annoys me more than cut-scenes, are cut-scenes that can not be skipped! Yes, they do this. They make you watch stuff you do not really care about. There is no fast-forward, because they've gone to the trouble of making this, and you're going to watch it, dammit!

There really is no excuse for "non-skippable cutscenes". I am playing a game. You may think the game is so subtle that there's no WAY anyone could play it without the crucial information conveyed in the cutscenes. You'd be wrong. 99% of the time, it's like this: if it moves, shoot it. End of story. If there really is important information to be conveyed, there are other ways to accomplish that besides forcing me to watch it played out on screen. Text springs to mind. Text has worked for millennia. I predict a bright future for it.

Sunday, September 27, 2009

Bootloading the Arduino over XBee ZB, Part II

Right, so I got the Arduino to load over XBee with the default bootloader. But I am still stuck with having to manually hit the reset-button on the Arduino.

So here is my plan. (I've seen various variations on this on the 'net, but not exactly what I want. Someone has probably done it, before, though. I don't care.) I wonder if that whole CTS hardwired to Reset can work for us his time. What I want is for the DTR, when received over the USB-connection by the XBee Coordinator, to magically reset the Arduino. This should in theory be very simple with the XBee shield.
  • On the XBee EndDevice, set DIO7 to mode 4, which is "Digital Out, Low". (ATD7=4, if you're doing it by hand)
  • Then, on the XBee Coordinator, set DIO7=Input (ATD7=3), and IC=80 (IC is a bitmap of which inputs to monitor, 40h is a bitmap with only the 8th bit set, counting from IO0)
  • Finally, solder a jumper on your XBee explorer, tying DTR and CTS together. (Actually, this should probably be a resistor.. I'm guessing CTS is an input on the FTDI. And Maybe it should be possible to revert this somehow, I think X-CTU depends on CTS and DTR for firmware-loading. Minor details!)
  • Done!
Looks good, no? This should work because the XBee's are quite intelligent little things. Because we set DIO7 on the Coordinator to Input, the XBee should automagically send this information to whichever XBee is addressed in the Coordinators DH/DL-registers (you did program those, didn't you?). And since we hardwired DIO7 to DTR, whenever AVRdude asserts DTR, the remote XBee will assert DIO7. And, as we know from bitter experience, DIO7 is hardwired to Reset on the XBee shield.

Sounds simple, doesn't it. Perhaps too simple.. I've struggled with this for a few hours, but no matter what I do, no matter what config, no matter what firmware, I can not get the target XBee to change its outputs.

I've concluded that this functionality ("transporting" Digital IO-lines) only works on Series 1 XBee's. Something that is not clear in the documentation. (As a sidebar, I would like to note that the XBee documentation in general is not all that great..)

Anyway, I've opened a case with Digi on this, hopefully they will come back with a clear answer. I'll update if they do!

Update! I've heard back from a very pleasant support-person at Digi, and he confirmed my suspicion. This is not supported on the XBee ZB, and it probably never will be. They also confirmed that this does work on their series 1 radios, the XBee 802.15.4.

So, what would the workaround be?? Well, I've verified that asserting DIO7 will reset the arduino. So I guess I'll write a small wrapper for AVRdude, which sends a package to the remote XBee instructing it to set DIO7 high, then low, and then fires up AVRdude. Might work. The bad news is that it will require the API firmware, at least on the Coordinator. Don't yet know if API Coordinator with AT EndDevice will have the desired effect. I do not yet know if I can make this work, if the EndDevice needs to have the API firmware in order to support remote commands, I don't think it will send the data straight out on the serial, but rather in a frame-structure. Meaning I'd need a custom bootloader in order to decode the data.. Hm.

So I suppose there will be a "Bootloading the Arduino over XBee, Part III". Sometime.

Bootloading the Arduino over XBee ZB

I was playing with the XBee and Arduino again, and reading a lot of posts about how to bootload the Arduino wirelessly over the XBee. It was a fairly intricate process, involving among other things a custom bootloader. Now, it should be said that most of these posts were fairly dated, so there may be something that's changed. Because when I tried it, it worked on first try, with the default bootloader.. Mysteriously.

Setup: XBee Coordinator on XBee USB Explorer on COM5, XBee EndDevice on Arduino Mega.

(BTW, if you read my previous post, this will not work with the rerouted Serial. Put both jumpers to 'XBEE' on the XBee Shield)

Anyway, here's how I did it.

  • Set up both XBee's to use 57600 baud.
  • Upload .hex-file using AVRdude. Here is my cmdline:
 avrdude -Uflash:w:ledXBee.cpp.hex:i -cstk500v1 -P \\.\com5 -pm1280 -b 57600 -D
  • At the precise moment you hit Enter, also press the reset-button on the Arduino. You may have to try a couple of times. Basically, methinks its because DTR isn't transmitted to the Arduino wirelessly, so you have to perform that duty yourself. I have an idea on how to fix it, but it requires some soldering..
  • Done.

A screenshot may be in order:

Ok, so that works like a charm. I must explain that the XBee's are 4 inches apart, and the binary is less than 3K. I don't know if it'll scale in size or distance.

So, over to that last pesky bit, having to hit reset manually.. But that will have to wait to another day.

XBee woes..

As I mentioned in my last post, I also procured a couple of XBee's and the XBee shield. I don't exactly know what the big idea with that shield is, as it really is a pain. In three ways:
  1. The CTS pin is hardwired to the reset-pin of the Arduino. You'd think that would be prominently displayed, but it isn't.
  2. It uses the same Serial as the USB. I have the Mega, so it might have more serials than the other Arduino's, I havent checked. (That would be the only reason I can see for doing this)
  3. It only connects a few of the pins.

Before I go on, I think I should explain my setup here, as it may to be crystal clear from the text alone..


  1. Arduino + XBee Shield + XBee (EndPoint), connected to COM4
  2. XBee Explorer + XBee (Coordinator), connected to COM5
  3. (Note to self: use bigger fonts)

So. Annoyance #1, the CTS-pin. That one threw me for a loop for a few hours. I have the XBee EndDevice on the Arduino (XBee ZB EndDevice, firmware 2x64). The Xbee ZB Coordinator is connected to my laptop, on the XBee Explorer. I uploaded the example sketch from Arduino "PhysicalPixel", which simply turns the LED on pin 13 off and on with the reception of a H or L on the serial-port.

With the default AT-firmware, I can now open the com-port where the XBee Coordinator is, set the DH/DL registers to the address of my EndDevice, and send H's and L's, observing the miracle that is a wirelessly transmittet blinking LED. Big Whoop.

This was, in itself, quite the little victory for me. Only, when the LED was on, I would ofcourse sit back and marvel at this little light (harbouring thoughts which included the words "evil" and "genious"). Only to observe that it turns itself off! For no reason what so ever! The code is so simple that it can not be a bug. So what is going on??

This is when Annoyance #2 hit me. Since the XBee and the USB FTDI shares the same serial-port, you must choose which one wins. This is done with a couple of jumpers, but it means that you can't simply add a few lines of code to the arduino to make it phone home with what is going on. Which makes it annoying to debug..

The "cure", so to speak, is exceedingly simple, at least on the Arduino Mega. Pull off the jumpers, connect the middle pin on each of the two jumpers to pin 18 and 19 on the arduino. It will then use Serial1 (as denoted in the Arduino GUI), instead of Serial, which allows you to fill your code up with "Serial.write("Hello");", and understand what is going on. (I simply use two instances X-CTU, on each of COM4 and COM5.)

(Note that in the picture I've left the jumpers connected to one pin, so I don't loose them. The blue socket is connected to the middle of the three pins, although it doesn't look that way in the photo..)

Very helpful, that.

Anyway, turns out the solution for Annoyance #1, Mysteriously Resetting Arduino is also extremely simple. When using X-CTU to configure your EndDevice, simply set IOD7=0 (or use ATD7=0, same thing). The XBee will no longer reset your Arduino simply because it wants to sleep.

Now, Annoyance #3. This one really occured to me while playing with this. Finally solving the two previous issues, I made a small program to let me connect to the EndDevice XBee on the Arduino through the USB-port. Very simple, read a byte from Serial, send it to XBee on Serial1. This way I could verify that the Arduino got the transmissions from the XBee Coordinator (by watching the Magic LED), and I could also enter command mode on the XBee EndDevice without pulling it off the XBee Shield.

This in itself was easy enough, but I noticed that the Xbee EndDevice, when sleeping, would not wake up from data on the serial-line (i.e. from the AVR). I don't know why. When I first sent something on the wireless side, it would wake up. As long as its awake, "talking" to it through the Arduino works just fine, but it will eventually go to sleep.

So. Another small "adustment" to the Xbee shield. First of all, I enabled Sleep Mode 5 (ATSM5) on the EndDevice. This sleepmode allows the microcontroller to wake the Xbee through pulling pin 9 (SleepRQ) on the XBee low. Fancy. Only, Pin 9 isn't connected anywhere on the Arduino! Annoying. Also, the XBee is 3.3v, while the Arduino Mega is 5v.

I "solved" this by soldering a 1.4Kohm resistor between pin 9 on the Xbee-socket and Pin 7 on the Arduino. Now, when I send anything on Serial (i.e. USB connected to my laptop), it pulls pin 7 (connected to pin 9 on XBee), low. This causes the XBee to wake up, and it is under my command. World domination must start somewhere, and I now consider myself well on the way.

A picture for the curious:



In case you're wondering why I chose a 1.4Kohm resistor, here's why:

  • The Arduino is 5v, the XBee is 3.3v
  • The XBee can sink maximum 4mA
  • The Internet told me 5V through 1.4Kohm equals 3.57mA. So won't fry the XBee.

So, in conclusion.. I now have a setup which allows me to

  1. Send random crap from my laptop, through the XBee Coordinator in COM4, to the Arduino.
  2. The Xbee EndDevice does not randomly reset my Arduino
  3. The Arduino can phone home over COM5 to my laptop.
  4. The Arduino can set a LED, in order to let me know it receives the stuff I send to it wirelessly (and because you have to have a LED)
  5. I can send AT-commands to the XBee EndDevice through the Arduino on COM5.
  6. The Arduino will wake the XBee up, so that it will Obey My Command.

Here's my Sketch:

/*

Hardware-mods:
- Pin 9 on XBee connected through 1.4Kohm resistor to pin 7 on Arduino (Any pin, allows arduino to control sleeping on XBee)
- XBee RX connected to pin 19 (RX1) on Arduino (Allows Arduino to phone home on USB-serial, for easy debugging)
- XBee TX connected to pin 18 (TX1) on Arduino (Ditto)

XBee config-changes (from default):
SM=5 (If not using the Sleep_RQ pin, set SM=0, and use Router firmware)
D7=0 (CTS on XBee is hardwired to reset pin of Arduino. When XBee sleeps, Arduino resets.)

My setup
Coordinator connected to COM5 on USB XBee Explorer
Arduino connected through USB to COM4, XBee EndDevice on XBee Shield.

Why?
To play with the EndDevice XBee and try to work out what's going on! Send H or L through the XBee connected
to the XBee Explorer (i. e. Coordinator) and watch the LED change, as if by magic! Send AT-commands through
the COM-port connected to the Arduino to see what the EndDevice is playing at, reconfigure parameters etc.
*/

const int ledPin = 13; // the pin that the LED is attached to
const int sleepPin = 7; // Connected to SleepRQ on the XBee, SM=5

int incomingByte; // a variable to read incoming serial data into

int graceperiod = 5000; // Milliseconds to wait before allowing XBee to sleep, to make sure no more data incoming on USB serial
unsigned long timeout = 0;
boolean sleeping = true;

void setup() {
// initialize USB serial communication:
Serial.begin(9600);

// Initialize XBee comms
Serial1.begin(9600);

// Say hello.
Serial.write("Hello.");

// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);

// Pin7 now connected to Sleep_RQ
pinMode(sleepPin, OUTPUT);

// Xbee sleep
digitalWrite(sleepPin, HIGH);
}

void loop() {

// see if there's incoming serial data from XBee:
while (Serial1.available() > 0) {

// read the oldest byte in the serial buffer:
incomingByte = Serial1.read();

// Echo back to USB
Serial.write(incomingByte);

// if it's a capital H or h, turn on the LED:
if ((incomingByte == 'H') (incomingByte == 'h')) {
digitalWrite(ledPin, HIGH);
}

// if it's an L or l, turn off the LED:
if ((incomingByte == 'L') (incomingByte == 'l')) {
digitalWrite(ledPin, LOW);
}
}

// Data from USB is echoed to XBEee
while(Serial.available() > 0){

// If sleeping, set sleepPin high and wait for XBee to wake up
if(sleeping == true){
digitalWrite(sleepPin,LOW);
sleeping = false;
delay(500); // Pick a number..
}

// A character was received, renew timeout
timeout = millis() + graceperiod;

// Send data to XBee
Serial1.write(Serial.read());
}

// Put XBee back to sleep, after graceperiod (to make sure no more keypresses are incoming)
if((sleeping == false) && (millis() >= timeout)){
digitalWrite(sleepPin, HIGH);
sleeping = true;
}
}

So.. I just got this Arduino..

So, I decided (for no particular reason, I might add), to order a few geek gadgets. Namely, a couple of Arduino's, with all the fixin's. (Mega and 3v3 Pro, XBee's, with the obligatory XBee Shield and XBee Explorer from Sparkfun.)

Good stuff, I really like that I can get straight to programming it (yes, I have been staring at a stupid blinking LED for several days now, wondering quietly what I was thinking when I placed the order..) and I like how I dont have to spend days assembling all the "ancillary" circuits just to get the damn thing working. Most of all I like the fact that it can be programmed with the Arduino software and the bootloader. Which means, of course, that I have a platform for programming microcontrollers with simply a USB-cable and free software. No need to buy (or solder) an expensive (or cheap) programmer, no need to make a Decision as to which architecture to go with. Buy it, and go. Hassle free. Or so I thought..

So for the not-so-good stuff. Full disclosure; I've owned these things for exactly 3 days, so my knowledge of the hardware and software may not entitle me to an opinion.. I have one none the less. I have also next to no experience with electronics. That only puts me right in the target demographic for the Arduino.

From my understanding, the makers of Arduino (and the related projects) put this package together so that people could get started with HW-hacking quickly and painlessly. Which works just fine, up to a point. You see, the arduino GUI and language hides so much of what's going on under the hood that it becomes a pain to map the real hardware, lets start with the AVR1280 datasheet, to the Arduino software.

I quickly figured out that my path of progression would be something like

  1. Make the LED blink using the Arduino GUI
  2. Move on to AVR Studio and AVR GCC to get more control and understanding of the operation of the chips
  3. Use AVR Studio with ASM.
  4. Sit back and congratulate myself for understanding the AVR8 architecture, as well as buildtools

That last point would have to be done quietly, lest someone should overhear me. It would not do.

So, as I mentioned, Step 1: blinking LED, CHECK.

Moving on to Step 2 was more of a pain than I imagined. To recap, I have now written the obligatory blinking LED using the actual registers etc in AVR Studio 4, compiled it, and now I want my Arduino to execute it.

But the Arduino GUI gives no clue whatsoever on how the hex-file gets to your board. A little Googling will reveal it uses AVRdude, which sounds just fine. Of course, things arent a simple as that. I ended up digging through the sourcecode for the GUI to find the interesting bits, an lo and behold, you can add "upload.verbose=true" to your preferences file, which will output all the details on how it uses AVRdude! Success! (For the interested, it's in svn/trunk/app/src/processing/app/debug/AvrdudeUploader.java)

Erm.. No. For reasons I don't fully understand, it doesn't work with the stock AVRdude. Take the following example:

avrdude -Uflash:w:Test.hex:i -cstk500v1 -P \\.\com4 -pm1280 -vvvv -b 57600 \
-D -C\Ole\arduino-0017\hardware\tools\avr\etc\avrdude.conf

avrdude resolves to the version bundled with WinAVR, which I've installed for use with AVR Studio. It is pretty much an exact copy of what the Arduino GUI does. Still, it spits back at me

D:\Ole\Avr Studio Projects\Test\default>avrdude -Uflash:w:Test.hex:i -cstk500v1
-P \\.\com4 -pm1280 -vvvv -b 57600 -D -C\Ole\arduino-0017\hardware\tools\avr\etc
\avrdude.conf

avrdude: Version 5.6, compiled on Mar 5 2009 at 09:59:30
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/

System wide configuration file is "\Ole\arduino-0017\hardware\tools\avr
\etc\avrdude.conf"

Using Port : \\.\com4
Using Programmer : stk500v1
Overriding Baud Rate : 57600
avrdude: Send: 0 [30] [20]
avrdude: Send: 0 [30] [20]
avrdude: Send: 0 [30] [20]
avrdude: Recv:
avrdude: stk500_getsync(): not in sync: resp=0x00
avrdude: Send: Q [51] [20]
avrdude: Recv:
avrdude: stk500_disable(): protocol error, expect=0x14, resp=0x51

avrdude done. Thank you.
Thank you, indeed.. So. Now what? Turns out, someone must have patched something. If you specify the AVRdude.exe that comes with Arduino, it all works like a charm..

\ole\arduino-0017\hardware\tools\avr\bin\avrdude -Uflash:w:Test.hex:i -cstk500v1 -P \\.\com4 -pm1280 -vvvv -b 57600 -D -C\Ole\arduino-0017\hardware\tools\avr\etc\avrdude.conf
Is this behaviour documented? Quite possibly. It didn't show up in the first 10 results from Google (that I checked). My current guess is that is has something to do with DTR resetting the Arduino. If I use stock AVRdude, and reset the Arduino at precicely the right moment, it will load correctly. Topic for another post..

So, thats one hurdle overcome. Strangely, I couln't really find a cookbook recipe on how to use AVR Studio 4 with the Arduino.. Here is one.

1. Add "upload.verbose=true" to the preferences file of a working Arduino. (This must be done with the GUI shut down, or it will be overwritten)
2. Observe the output
3. Write and compile your program in AVR Studio
4. Upload, using the AVRdude from the Arduino, and using the options observed in step 2.
5. Rinse and repeat.