Monthly Archives: September 2018

Friday Product Post: No, I Am Your FPGA.

via SparkFun: Commerce Blog

Today we are excited to bring you the new Arduino MKR Vidor 4000, which combines the benefits of the SAMD21 and an FPGA. We also have the Raspberry Shake Home Earthquake Monitor, two Neutis boards to help fill the hole in your heart from the Edison’s passing, and a few other new products to fill your cart!

Vidor… Darth Vidor!

Arduino MKR Vidor 4000

Arduino MKR Vidor 4000

DEV-14870
$74.95

The Arduino MKR Vidor 4000 is highly configurable and powerful, and it can perform high-speed digital audio and video processing. With the Vidor, you can configure it the way you want to essentially create your own controller board. It comes loaded with hardware and potential: an 8 MB SRAM, a 2 MB QSPI Flash chip (1 MB allocated for user applications), a Micro HDMI connector, an MIPI camera connector, and Wifi and BLE powered by U-BLOX NINA W10 Series. It also includes the classic MKR interface, where all pins are driven both by SAMD21 and FPGA. Plus, it has a Mini PCI Express connector with up to 25 user programmable pins.


This shake brings an easy-to-use earthquake monitor to the yard!

Raspberry Shake - Home Earthquake Monitor (RS1D)

Raspberry Shake - Home Earthquake Monitor (RS1D)

SEN-14835
$214.99

The Raspberry Shake is a highly accurate seismograph you can use in your home, office and classroom. This Raspberry Pi accessory uses a single, vertical geophone as its sensor – a very sensitive yet rugged Earth motion microphone, widely used in the oil and gas industry to detect seismic vibration. The Raspberry Shake was originally designed with citizen scientists and educational facilities in mind, but can easily be used by other hobbyists, makers and enthusiasts!


Neutis Quad-Core Module

Neutis Quad-Core Module

DEV-14971
$59.95
Neutis Development Kit

Neutis Development Kit

DEV-14972
$239.95

Even though we made these available at the end of last week, we wanted to bring attention to these “Edison replacements” this Friday! The Neutis Quad-Core Module and Development Kit are loaded with features. Utilizing Neutis’ BSP based on Yocto, the system arrives with an up-to-date Linux kernel. The module is powered by a 64-bit ARM Cortex-A53 and a ARM Mali450 MPR GPU. It has 512 MB of RAM and 8 GB of eMMC storage. For connectivity, there are a plethora of wired and wireless options at your disposal. For wireless needs, the system rocks 802.11 b/g/n and Bluetooth 4.0 Dual-mode BLE, all with the built-in antenna. For your wired needs, the module’s two connectors give you access to an incredible peripheral set, including over 50 GPIO and a multitude of interfaces.


ESP-WROVER-KIT

ESP-WROVER-KIT

WRL-14917
$40.00

The ESP-WROVER-KIT is a development board produced by Espressif built around ESP32. This board is compatible with most ESP32 modules, including the ESP32-WROOM-32 and ESP32-WROVER (which you will find on the board itself). The ESP-WROVER-KIT features support for multiple amenities not typically found on other IoT devices, including a microSD card port, camera and LCD inputs, power mode selection and more. Each of the I/O pins have been broken out from the ESP32 module for easy extension, should you choose to use them.

We also have a few other new products to check out, so make sure to check out our New Products Page to see them all!


That’s it for this week, folks! As always, we can’t wait to see what you make! Shoot us a tweet @sparkfun, or let us know on Instagram or Facebook. We’d love to see what projects you’ve made!

We’ll be back next week with even more fantastic new products!

comments | comment feed

Enginursday: Creating Random Sequences with Rules

via SparkFun: Commerce Blog

When you put a bunch of electronics around trampolines in a room, and ask thousands of kids to jump on them, it’s only a matter of time before something fails. About three weeks after Boulder Bounces opened, we got an email telling us that it was failing on occasion.

alt text

Background of the project

We recently designed and installed an exhibit at the Museum of Boulder called Boulder Bounces. It’s a memory game much like the Simon Says Soldering Kit, but with trampolines. You can read more about it at this blog post, or watch the following video:

The original Simon Says uses the built-in random() Arduino function. While this works fine for the original game, Boulder Bounces needed some extra rules in the sequence generation to avoid “boring” bounce patterns. It’s not that fun to have many repetitions of the same trampoline, and any repetitions in the beginning of the sequence are not only difficult, but can lead to some serious confusion for the first-time player. Plus, when you’re playing with a group of jumpers (each standing on their own trampoline), it is loads more fun to ensure everyone gets to jump.

Let the investigation begin!

I have a lot of serial debug messages sending out from my Arduino Pro Mini on this project, so I was eager to plug in a FTDI basic and hear what was going on. My original email from the museum said that if they simply cycled power, it would start working again. Because of this, my first thought was that it was most likely failing in software, and not a hardware issue.

When I opened up the panel on the wall, it looked like the LEDs had been mistaken for buttons and pushed completely back into the panel. Those darn kids! I guess I can’t blame them; the gumdrop LEDs are big enough to be a button, but I needed to stay focused on the problem at hand.

Jumping right in

I played through an entire game once. It worked just fine. I played another round. No issue. Again, and again. Nothing. Then on the sixth game, right before I should have heard the winning sounds, it seemed to stall out.

I went to look at my serial debug, but it seemed to stop spitting out any serial debug at all. Hmmmm. When I am troubleshooting a code bug that involves a “stall out” like this, my first approach is to verify the point of failure and then work backward to find out the potential issue.

During my last game (right before the failure), I remember my serial debug was working properly. It was outputting each new sequence after each successful play correctly. But at my “win,” the serial debug stopped, so the failure must be occurring somewhere immediately after the last add_to_moves() was called.

A high-level look at the original code

Before we jump into any of the original code, I think it would be beneficial to share the high-level plan for gameplay, and my higher-level approach to creating the random sequence with rules.

The original gameplay code worked like this:

When you are playing a game, the Arduino will “play” back the sequence to you. At first, it only shows one trampoline light up, and you jump on it. Then the Arduino “randomly” chooses the next trampoline to add to the sequence. It plays back the entire sequence (which at this point is only two jumps long), and you must jump the sequence in order. Then it adds another, and so on. Once the sequence reaches eight and you successfully jump in the correct order, you win!

The specific part of the code that I’m talking about today is a function called “add_to_moves()”. This is a simple enough function in theory. Let’s take a look at the original function from the original Simon Says to start. Note, this code is from the button game, and was not used on the trampolines installation, but it’s a good place to start.

void add_to_moves(void)
{
  byte newButton = random(0, 4); //min (included), max (exluded)

  // We have to convert this number, 0 to 3, to CHOICEs
  if(newButton == 0) newButton = CHOICE_RED;
  else if(newButton == 1) newButton = CHOICE_GREEN;
  else if(newButton == 2) newButton = CHOICE_BLUE;
  else if(newButton == 3) newButton = CHOICE_YELLOW;

  gameBoard[gameRound++] = newButton; // Add this new button to the game array
}

First, you notice that the “random(0,4);” is generating the next “newButton” in the sequence. The following five lines of code are not really important in this discussion, but to quickly explain, we need to change them to the defined variables associated with each button choice available. For today, let’s just focus on the creation of newButton and then how it is added to the array, gameBoard[].

Looking at the original function add_to_moves(), it simply uses random() to add a new button to the sequence. This worked fine for the original Simon Says, but for Boulder Bounces, we needed to add in some rules to make it more interesting.

Add a while loop and some rules

My first approach to adding rules was to put it in a while loop. Inside this while loop, it would first grab a random newButton value from random(), then compare it against some rules. If it passes all the rules, then it would use it, and break out of the while loop. If it doesn’t pass a rule, then it would do nothing, stay in the while loop and try again.

alt text

The problem with this approach is that it is living on a prayer that random will eventually return something that will pass the rules. I knew this wasn’t perfect, but in all my development work on this project I never saw it get stuck. It usually tried a couple times at most, but eventually returned something that would work. It turns out that it can get stuck there, and something was causing it to stop trying.

For reference, the original code (with the actual rules - aka “if” statements) is as follows. You can see all of it here on my github commit. Specifically, here is my original add_to_moves():

void add_to_moves(void)
{
  while (1)
  {
    newButton = random(0, 3);
    if (!((newButton == gameBoard[gameRound - 1]))) // avoid repeats
    {
      // check to see if that button is already "maxed out"
      if ((newButton == 0) && (RED_seq_count == 2)); // do nothing
      else if ((newButton == 1) && (GREEN_seq_count == 3)); // do nothing
      else if ((newButton == 2) && (BLUE_seq_count == 3)); // do nothing
      //else if((newButton == 3) && (YELLOW_seq_count == 2)); // do nothing
      else break; // get out of this while loop and continue playing.
    }
  }

  // We have to convert this number, 0 to 3, to CHOICEs
  if (newButton == 0)
  {
    newButton = CHOICE_RED;
    RED_seq_count++;
  }
  else if (newButton == 1)
  {
    newButton = CHOICE_GREEN;
    GREEN_seq_count++;
  }
  else if (newButton == 2)
  {
    newButton = CHOICE_BLUE;
    BLUE_seq_count++;
  }
  else if (newButton == 3)
  {
    newButton = CHOICE_YELLOW;
    YELLOW_seq_count++;
  }

  gameBoard[gameRound++] = newButton; // Add this new button to the game array
}

You may also notice that my rules rely heavily on some new variables: RED_seq_count, BLUE_seq_count, etc. These are helping me keep track of how many times I’ve already included a specific color button in the sequence, so I can avoid favoring any button and ensure everyone gets to jump.

In an attempt to hone in on the problem, I added a little line of debug at the end of my add_to_moves() function.

if(debug) Serial.println("add_to_moves attempting...");

Now I would know whether it was trying at all, getting stuck in this while loop or stalling out elsewhere.

After much jumping and winning, I got another failure in the middle of a round. It stalled out, and my serial monitor looked like this:

alt text

Remember, my first failure was just before a “win.” Because this second failure was in the middle of a game, this was a new clue! This means that the failure is caused somewhere else in the code, and probably has nothing to do with the code just before a win.

Right before it stalled out, the entire serial monitor was filled with the message “add_to_moves attemping…” It was sending this message again and again as fast as my little Pro Mini could go. Something strange was going on. Why would it get stuck repeating this message, and then eventually give up?

The speed of the repetition of the debug message was also strange. When it seemed to be trying normally, the message would spit out to the terminal at a moderate pace. But when the failure would occur, the messages would speed up dramatically and eventually cause a stall out. After much finagling and many attempts to cause failures, I eventually gave up trying to find the root cause. I knew there was a better way, and so decided to start a different approach the the random generator with rules.

A better approach

alt text

To elliminate the possibility of any stall-outs, I introduced a new array called “on_deck_buttons[].” I would have my rules adjust this array, and then my random function can just choose from the good options. That way, random() will only be called once, and this removes the need to loop back around and try again and again.

I also beefed up my debug to get a better view into what was actually going on with all my variables and arrays.

Here is my new add_to_moves() function:

// Adds a new random button to the game sequence
void add_to_moves(void)
{
  byte newButton = random(0, 3); //min (included), max (exluded)
  int add_to_moves_counter = 0; // keep track of our while loop below for finding good new buttons, and see if this is jamming the game.
  if(gameRound == 0); // do nothing - newButton is randomly set above.
  else if((gameRound == 1) || (gameRound == 2)) // jumps 2 and 3 are important. for the first 3 jumps we want these to always hit each tramp once
  {
    while(1)
    {
      add_to_moves_counter++; // keep track of how many times we are trying to find a good new button to use (random might be stalling out here)
      int on_deck_buttons[2] = {0,0}; // these are used to help reandomize below
      newButton = random(0, 3); // pull in a first attempt at a nice new random button
      if((newButton == 0) && (RED_seq_count > 0))
      {
        on_deck_buttons[0] = 1;
        on_deck_buttons[1] = 2;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;
      }
      else if((newButton == 1) && (GREEN_seq_count > 0))
      {
        on_deck_buttons[0] = 0;
        on_deck_buttons[1] = 2;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;
      }
      else if((newButton == 2) && (BLUE_seq_count > 0))
      {
        on_deck_buttons[0] = 0;
        on_deck_buttons[1] = 1;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;        
      }
      //else if((newButton == 3) && (YELLOW_seq_count == 2)); // do nothing
      //else break; // get out of this while loop and continue playing. This means that the new button is good to go. 
      else
      {
        Serial.println("error");
        break;
      }
      if(debug) Serial.println("add_to_moves attempting...");
      if(debug) Serial.print("gameBoard[gameRound-1]:");
      if(debug) Serial.println(gameBoard[gameRound-1]);
      if(debug) Serial.print("gameBoard[gameRound-2]:");
      if(debug) Serial.println(gameBoard[gameRound-2]);      
    }
    if(debug)
    {
      Serial.print("add_to_moves_counter: ");
      Serial.println(add_to_moves_counter);
      Serial.print("RED_seq_count: ");
      Serial.println(RED_seq_count);
      Serial.print("GREEN_seq_count: ");
      Serial.println(GREEN_seq_count);
      Serial.print("BLUE_seq_count: ");
      Serial.println(BLUE_seq_count);
    }
  }  
  else // only after you make it to step 3.
  {
      // attempt 1, works.
      // while((newButton == gameBoard[gameRound-1]) && (newButton == gameBoard[gameRound-2])) newButton = random(0, 4); // keep pulling in more variables until this isn't true.
      // basically, if it's the same as the previous 2 buttons, then it will keep finding a random number until it's "fresh".

      // attempt 2, attempting to add in limit per button to avoid leaving one jumper out.
    while(1)
    {
      add_to_moves_counter++; // keep track of how many times we are trying to find a good new button to use (random might be stalling out here)
      int on_deck_buttons[2] = {0,0}; // these are used to help reandomize below
      newButton = random(0, 3); // pull in a first attempt at a nice new random button

      // This ensures it's not going to repeat same button 3 times
      //if((convert_to_choice_byte(newButton) == gameBoard[gameRound-1]) && (convert_to_choice_byte(newButton) == gameBoard[gameRound-2])); // do nothing, try again 
      // check to see if that button is already "maxed out" (aka it has been used twice already)

      if((newButton == 0) && (RED_seq_count == 2))
      {
        on_deck_buttons[0] = 1;
        on_deck_buttons[1] = 2;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;
      }
      else if((newButton == 1) && (GREEN_seq_count == 3))
      {
        on_deck_buttons[0] = 0;
        on_deck_buttons[1] = 2;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;
      }
      else if((newButton == 2) && (BLUE_seq_count == 3))
      {
        on_deck_buttons[0] = 0;
        on_deck_buttons[1] = 1;
        newButton = on_deck_buttons[random(0, 2)]; // chooose randomly from on_deck_buttons - aka the only ones we want to choose from
        break;        
      }
      //else if((newButton == 3) && (YELLOW_seq_count == 2)); // do nothing
      //else break; // get out of this while loop and continue playing. This means that the new button is good to go. 
      else
      {
        Serial.println("error");
        break;
      }
      if(debug) Serial.println("add_to_moves attempting...");
      if(debug) Serial.print("gameBoard[gameRound-1]:");
      if(debug) Serial.println(gameBoard[gameRound-1]);
      if(debug) Serial.print("gameBoard[gameRound-2]:");
      if(debug) Serial.println(gameBoard[gameRound-2]);      
    }
    if(debug)
    {
      Serial.print("add_to_moves_counter: ");
      Serial.println(add_to_moves_counter);
      Serial.print("RED_seq_count: ");
      Serial.println(RED_seq_count);
      Serial.print("GREEN_seq_count: ");
      Serial.println(GREEN_seq_count);
      Serial.print("BLUE_seq_count: ");
      Serial.println(BLUE_seq_count);
    }
  }

  // We have to convert this number, 0 to 3, to CHOICEs
  if(newButton == 0) 
  {
    newButton = CHOICE_RED;
    RED_seq_count++;
  }
  else if(newButton == 1) 
  {
    newButton = CHOICE_GREEN;
    GREEN_seq_count++;
  }
  else if(newButton == 2) 
  {
    newButton = CHOICE_BLUE;
    BLUE_seq_count++;
  }
  else if(newButton == 3) 
  {
    newButton = CHOICE_YELLOW;
    YELLOW_seq_count++;
  }

  gameBoard[gameRound++] = newButton; // Add this new button to the game array
}

The trouble with failures that only happen once in a while is that it can require lots of data points and repeated testing to emulate the failure. For most software issues, this can sometimes be automated and done quickly, however, with exhibits like these that involve physical hardware, the true game play must be cycled again and again to create the failure.

The trampolines were failing randomly every 10-20 game plays, so that meant a lot of jumping. Never in my life have I had such a physically demanding code debug session! I did my fair share of jumping during the development of this project, but that paled in comparison to this debugging session.

If you have experienced any strange stall-out with the random() function, or have any other approaches to creating sequences like this, please share in the comments below. Also, please check out the github repo link below, and if you so feel inclined, we always love seeing any issues, forks, pull requests or comments. Thanks for reading and happy coding!

Boulder Bounces Github Repository

comments | comment feed

SIK Project Ideas: Locker Alarm

via SparkFun: Commerce Blog

A few weeks ago I began to share some projects using parts from the SIK v4.0 to inspire users beyond the guide book. Today’s project was most certainly inspired by all of the cool back-to-schoool projects I wrote about last week – ladies and gentlemen, I introduce the Locker Alarm!

The locker alarm is a project using parts found in the SIK v4.0, so if you happen to have one at home, you are all set. The project includes a SparkFun Redboard, a breadboard, the SparkFun baseplate, the piezo speaker, a momentary pushbutton and photocell, a 330 ohm resistor, a 10k ohm resistor, and a AA battery pack and jumper wire.

locker alarm project

The diagram below illustrates the circuit. As you can see, the piezo speaker has two leads that are NOT polarized, meaning either can go to power or ground. In this circuit, one of the leads should go directly to ground, with the other connected to pin 6. Our next component, the button, also has two non-polarized leads. One lead will go directly to power and the second will go both to ground, via a 10k ohm resistor, and directly to pin 2. Finally we have the photocell. This guy has two non-poloraized leads as well. One will go to power, and the other to both ground, via a 330 ohm resistor, and directly to pin A0.

locker alarm circuit

Having a hard time seeing the circuit? Click on the wiring diagram for a closer look.



Now it s time to program our Arduino. The photocell is constantly checking the light level. If it is dark, then nothing should happen because the locker is closed. If the locker is opened, the photocell will register the light and trigger an alarm tone on the piezo speaker. The button will turn off the alarm, so it might be a good idea to hide the button somewhere discreet. Once the button is hit, the Arduino stops playing the alarm tone. The alarm will not be triggered again until the locker has been closed and reopened.

You can use the program below to get the alarm running, or you can challenge yourself to write it on your own! In any case, I have added some comments to my code to explain some of the logic!

//Locker Alarm by Melissa Felderman for SparkFun Electronics September 2018

int photoCell = A0; //declare photocell to pin A0
int photoVal; //declare variable to hold photocell value
int momBut  = 2; //declare momentary pushbutton to pin 2 (interrupt pin)
int butVal; //variable to hold the value of the momentary pushbutton
int piezo = 6; //declare piezo speaker to pin 6

//the below booleans are used for the alarm logic in the if statements in the loop. Both should be set to false at the top of the program
bool turnOnAlarm = false;
bool state = false;



void setup() {

  pinMode(6, OUTPUT); //let the arduino know that the piezo pin is an output
  pinMode(momBut, INPUT); //let the arduino know that the button is an input
  attachInterrupt(digitalPinToInterrupt(momBut), alarmOff, HIGH); //attach an interrupt to pin 2(the button) we do this so the button will register even during a delay

}

void loop() {

  photoVal = analogRead(photoCell); //read the photocell value and store it in the photoVal variable

  //the if statements below create the logic for the alarm. If the photocell reads a high light value and the state boolean is false, trigger the alarm
  //this will then change the booleans 'state' and 'turnOnAlarm' to true. While 'turnOnAlarm' is true, the alarm sound will play (funtion alarm();)
  //if the button is pressed(per the attach interupt in the setup), a function will be triggered 'alarmOff();' which turns the
  //boolean 'turnOnAlarm' back to false, so the alarm will stop playing. The alarm will not turn back on even though the photocell is
  //recieveing light because the boolean 'state' is still true. This boolean will remain true until the locker is closed and the
  //photocell is recieveing no light again, essentially resetting it for the next time.
  if (photoVal > 300 && state == false) {
    turnOnAlarm = true;
    state = true;
  } if (turnOnAlarm == true) {
    alarm();
  } if (turnOnAlarm == false) {
    noTone(piezo);

  }
  if (photoVal < 300) {
    state = false;

  }



}

//below is an alarm function this uses the tone fucntion to make the alarm sound on the piezeo. This function is called while 'turnOnAlarm' is true
void alarm() {

  for (int hz = 440; hz < 1000; hz += 25) {
    tone(piezo, hz, 50);
    delay(5);
    for (int i = 3; i <= 7; i++);

  }
  // Whoop down
  for (int hz = 1000; hz > 440; hz -= 25) {
    tone(piezo, hz, 50);
    delay(5);
    for (int i = 3; i <= 7; i++)
    {

    }
  }
}


//This function is triggered when the interrupt button is hit. If changes the value of 'turnOnAlarm' so that the user
//can stop the alarm while the locker is still open and the photocell is recieving light.
void alarmOff() {
  turnOnAlarm = !turnOnAlarm;

}


That’s all it takes to make your very own alarm locker. As is, you can stick this bad boy with the AA battery pack on the inside of your locker door with some 3M foam tape, and it’s ready to go. However, there is still plenty of room to take it a step further. If you have access to digital fabrication tools like a 3D printer or laser cutter, try to make an enclosure for your alarm. I made one on the 3D printer, hoping to amplify the sound of the piezo using an inverted cone shape.

locker alarm 3d printed enclosure

For even more advanced makers, try setting an alarm that wirelessly sends you a notification of the breach. Maybe you could turn it off remotely too! This project is not limited to students with lockers - it will work in any small enclosed space, like a desk drawer or closet. There is a ton of room to build, expand and improve upon this project! Tell us know your thoughts and ideas in the comments below!

comments | comment feed

Creating a big, dangerous joystick with the Xbox Adaptive Controller

via SparkFun: Commerce Blog

For millions of people, gaming can be a way to wind down, a way to interact with family and friends, even a way of life. But for almost a quarter of all gamers, operating the controller can be an impediment to enjoying your favorite game. According to research done by Microsoft, 14 percent of gamers have a temporary mobility limitation, while eight percent have some type of permanent mobility limitation or disability that makes using the standard Xbox controller difficult, if not impossible. But this doesn’t change the fact that playing video games is dope. So Microsoft set out to do something about it.

Xbox adaptive Controller in hand

The Xbox Adaptive Controller, with its impressive array of input ports

Microsoft spent three years partnering with occupational therapy groups and nonprofits to come up with a controller that allows easier access and a customizable interface for gamers of all abilities – and what they’ve come up with is pretty impressive.

The large, 29.2 cm x 13 cm controller has on its face two large buttons (A and B) and a D-pad, along with the Xbox button, view button, menu button, profile button and a battery indicator light. But the really impressive part sits along the back edge: 19 ports that represent every button on a standard Xbox controller. The user can plug in any number of buttons, switches or pedals that have a simple 3.5 mm jack, allowing customized control of gaming inputs to make it as comfortable and enjoyable an experience as possible. Four of the inputs - eight, nine, 12 and 13 - can accept analog as well as digital signals. There are also a pair of USB 2.0 ports, one on each side, for HID joysticks or gamepads. Finally, a 3.5 mm headphone jack allows the gamer to keep peace among family, roommates or neighbors. And to charge the controller, there’s a USB-C power port and a DC power port, to keep your adaptive controller powered for up to twenty five hours.

Aside from its obvious use with the Xbox system, the Adaptive Controller can also be used with Windows 10, 7 and 8.1, although there will be limited functionality with the latter two. Additionally, it is completely re-mappable using the Xbox Accessories App, and Microsoft offers a decent variety of accessories to plug into the Adaptive Controller. But what I feel is one of its best features is the fact that it is not proprietary - that is, it can use any third party buttons, joysticks, switches or pedals, or even custom made ones. So that’s what I’m going to try today.

I’ve wired up some simple switches, and I will be plugging them into the Adaptive Controller and attempting to do some simple gaming on my PC. I don’t have an Xbox for testing, as I have always been a PS guy (kindly send all gamer-related hate mail to RobDontCare@sparkfun.com).

For games downloaded from the Microsoft Store, your controller should be automatically recognized, at least on a Windows 10 machine. You can still use your controller for other games, but you’ll need a third-party mapping application. I am using (Antimicro)[https://sourceforge.net/projects/antimicro.mirror/], but there are a number of other mapping apps available, such as Keysticks, JoyToKey and GlovePIE, to name a few. If you’re feeling really ambitious, you could probably even use this to make a fully immersive flight simulator cockpit, with an entire panel of switches spread out before you. Or you could just do something a bit easier, like I did for this demo project.

So this was just a bit of fun at the expense of my dignity, but the capabilities of this piece of hardware go far beyond the laughs we had here. If you or someone you know has a mobility limitation or disability, and want to connect with others or get more information on gaming accessibility, some of the groups that Microsoft worked with include:

https://warfighterengaged.org/ - This all volunteer group “provid[es] enabling solutions and independence to our wounded and severely disabled warfighters.”

https://ablegamers.org/ - Nonprofit organization dedicated to helping gamers with disabilities overcome social isolation through more accessible gaming options.

https://www.specialeffect.org.uk/ - A UK-based nonprofit dedicated to “put[ting] fun and inclusion back into the lives of people with physical disabilities by helping them to play video games.”

And if you want to learn a bit more about the Adaptive Controller from the source, take a look here: https://news.xbox.com/en-us/2018/05/16/xbox-adaptive-controller/

comments | comment feed

Desk of an Engineer: the Shawn Edition

via SparkFun: Commerce Blog

We’re back with more desk details! This is a series where we barge in on our engineers while they’re working and kick them out so we can document their desks in all their chaotic glory. And because we know that just isn’t enough information, we ransom their offices back to them in exchange for some details on what they have on their desks and why. We do this for you!

Clicking the image will enlarge it, so you can experience the full resolution of each engineer’s home away from home.

Today we’ve inconvenienced Shawn…for the last time.


Sad news, everyone. This is my last week at SparkFun. I have had a wonderful time working with some incredibly smart and talented people along with opportunities to make cool products and a few bizarre projects. As a way to take a trip down memory lane, Chelsea the Destroyer offered me the chance to show off my work area as one last goodbye post. I’ll show you how my workbench has evolved over the years and link to some of the fun memories associated with parts found around it.

Shawn's desk at SparkFun

The first noticeable aspect is likely the sheer size of the desk itself. If any of you were around 4 years ago, you might remember a post that I wrote where I talked about designing and building the desk.

When I first moved to Colorado, I knew that I wanted to upgrade from a small, barely-fits-a-laptop desk to something more appropriate for working with electronics. My initial plan was to buy an electronics workbench, which proved mostly fruitless considering most were north of $1,000 (new, at least). Not happy with the design of most commercially available workbenches, I set out designing my own with SketchUp to include all the custom features I wanted:

  • L-shape: one side for computer and the other for soldering equipment
  • Large surface area on main area for monitor, mouse, keyboard and various in-progress projects – I went with 72 x 30 inches
  • Countertop height (36 inches) so I could sit or stand as needed
  • Large enough area under the hutch to house one or more 24-inch monitors
  • Deep enough hutch to hold test equipment (e.g. oscilloscope) – I figured 18 inches was enough

Funny story, I actually made two desks with the same basic design. The first resides at my home, and the second was created to replicate the home setup at SparkFun. I noticed a problem with the first model: It wobbled. Thanks to the gracious help of SFUptownMaker, I added triangles to make the second model far more stable. I eventually went back and upgraded the first model with similar triangles.

Shawn's soldering workstation

Hanging off the edge of the smaller desk on the left (assuming you are standing at my desk) is a wire holder that I made a couple years back out of Actobotics parts. I got tired of scrounging around in random parts bins for a particular size, type, and color of wire.

Starting with the soldering area on the left , you’ll find some familiar equipment:

Wire rack

Behind the soldering desk and attached to the larger desk is my growing collection of cables and test leads. I try to keep them mostly organized with a Pomona test lead holder, but I fear it has nearly reached its limits. Coworkers seem to benefit most from my (apparent) organization, as folks will stop by quite often to “borrow” wire from the wire holder or cables from the rack. I’m just glad it’s getting used (and to be honest, I don’t want the cables back most of the time – it’s already too crowded!).

Close up of Shawn's desk

On top of the hutch, I keep my power supply and oscilloscope for testing various projects (or causing capacitors to explode). You’ll also find an old-school lamp, several mugs, a business card holder and a few Lego models (because AFOL).

About a year ago, I added pegboard to the back of the desk, which proved incredibly handy for housing everyday items like scissors, a ruler, multimeter, various types of tape, SD card holder and, of course, a Nerf gun.

On the left side under the hutch, you’ll see a Raspberry Pi attached to a 7-inch LCD along with a wireless keyboard/touchpad combination. This setup has proved invaluable over the last three months while working on several Python tutorials.

Beneath my dual-monitor setup, you can find an Analog Discovery 2 and some FTDI USB-to-Serial boards scattered about. I switch between the Analog Discovery and larger oscilloscope depending on my needs/mood. All my USB connections go through a hub, which has some buttons on top for enabling/disabling ports. I never thought I would need power buttons on a USB hub, but when you need to reset various 5V electronics and microcontrollers, they are a godsend.

The speakers remained largely unused, mostly due to being in an open office, but also because I recently acquired a set of Sennheiser HD 650 headphones that are fed from a JDS Labs ODAC and Objective2 amplifier. My ears are pretty happy.

The external hard drive nestled in the corner behind my plethora of liquid-holding vessels gets connected to my laptop each morning and stores the (rather large) files needed for video editing. SparkFun has an amazing videographer, Graceflix, who handles almost all of the video work. However, every so often, I will help out by editing my own screen capture before sending her the clips to integrate into the final piece.

I like to keep a few projects around that remind me of the good times, and one of my favorite product/project combos I worked on at SparkFun was BadgerHack. This was a soldering kit that booth attendees (at SXSW 2015 and NoCo Mini Maker Faire 2015) could put together before taking to one of two “programming stations” to upload simple pictures, animations or scrolling words of their choice. BadgerHack was an extremely fun group effort to create an unique experience for SparkFun fans and newcomers. I still keep a BadgerHack badge around for the memories, and you can see it hanging on the right side of my desk (behind the not-quite “Lego” mug).

I skipped over my mouse and keyboard setup, but it’s worth mentioning that I moved to a trackball about a year ago (my wrists finally started hurting after years with gaming mice). I still keep a Logitech G602 underneath the keyboard/mouse riser for screen capture moments.

The drawers beneath the desk house mostly basic office items: files, pens, pencils, tape and the like. Two drawers are worth noting, however. The first is the top drawer on the left; it holds a variety of soldering hand tools (cutters, tweezers, wire strippers, solder sucker, solder wick, etc.) laid out in an organized fashion. If I’m soldering, I just need to open the drawer and grab what I need. The second worthwhile drawer is on the bottom left; it holds food. Everyone should have a snack drawer.

Laptop perch in a bookcase

The bookcase to the right of the desk might seem like an odd addition, as it’s just placed in-line with the desk. However, it serves an important role: it keeps my laptop off my desk. About two years ago, I bought a high-end laptop with the intention of going to one computer to serve all my needs (no more sharing files between my work desktop, my other aging laptop, and my home desktop) – everything would be stored on one laptop that I would take with me at all times.

I cut a hole in the back of the bookcase to run a set of wires. Video and USB go to my desk, and an Ethernet cable connects me to SparkFun’s network. I mounted a power strip to the side of the bookcase to power my laptop, monitors and various other accessories.

That just about covers everything at my desk, at least everything within arms' reach. Not shown: several shelves with still-growing piles of electronic parts and dilapidated projects. My new goal is to adopt many of the Work Clean habits of chefs to keep my work area free of clutter (or at least organize the clutter). Keeping a workbench clean has proven quite difficult, as I’m sure anyone who has built electronics projects can attest. Oh well, I suppose that will just be another life goal for now.


Thanks Shawn! Bon voyage!

comments | comment feed

New product: Romi Chassis Expansion Plate

via Pololu Blog

The Romi Chassis Expansion Plate is now available and is a great way to add even more space to the Romi. It is designed to function as a modular expansion option for the Romi. In fact, if you have been following our new product announcements, you might have already seen this plate as part of the Robot Arm Kit for Romi. The expansion plate is a half circle with the same diameter as the Romi base plate, and it can be installed over either the front or rear half of the Romi chassis. Abundant mounting holes and slots cover the plate, matching the pattern used on the Romi chassis base plate and supporting various sizes of screws.

You can combine two plates to make a full-sized platform.

It is also possible to stack multiple expansion plates for even more versatility.

Continuing with the special introductory discounts for all of our new products this year, the first 100 customers who use coupon code ROMIEXPINTRO can get up to 3 Romi Chassis Expansion Plates for just $3.33 each!