ATtiny Bitsy Spider

Originally posted on www.letsmakerobots.com

ATtiny Bitsy Spider

UPDATE: Added BOM corrections. (Sorry for floating.)

Ok. Here’s a finished board I’ve been working on for a bit.

In essence, it is a BLE node board. It combines an HM-10 board with an ATtiny 85. This board builds off:

  1. Bluetooth 4.0 (HM-10)
  2. ATtiny 85

The idea of the Bitsy Spider board is diminutive controller node. I wanted it to be cheap and versatile enough to use as a node, but I think the final price is around $11 each.

Here’s the ole GitHub:

The BOM:

  1. OSHPark Board: $1.68 each ($5.05 minimum).
  2. 1 x 20k Resistor – 0402: $.04
  3. 3 x 10k Resistor – 0402: $.04
  4. 2 x 1uF 0402 $.20
  5. 3 x BSS138: $.60
  6. 1 x ATtiny 85 – SOIC: $.80
  7. 1 x HM-10: $6.50
  8. 1 x 0603 LED $.11
  9. 1 x 3.3V LDO 300mA – SOT-23-5 - Voltage Regulator: $.58

Total (approximate): $10.55

There are lots of solder-jumpers on this board, given it is meant to be versatile.

Here is the programming pinout to use an Arduino as ISP

The board is intended to harness the serial connection of the HM-10. In this version I made it straight forward, you leave the jumpers between the RX/TX line of the HM-10 and the ATtiny unsoldered, program the ATtiny as many times as you like. To test your serial connection between the ATtiny and the HM-10 simply breadboard the PCB and put jumpers like so:

PB0 <—> TX

** PB1 <—> RX**

This will allow you to test your code, without having to solder and unsolder. Then, after your code is perfectish, solder the jumpers marked “PB1 & HM10 RX” and “PB0 & HM10 TX,” then embed the Bitsy Spider.

This is an option that’ll probably continue throughout different versions of the board. I ran the GND connection of the ATtiny through a N-Chan MOSFET, and tied the gate of the FET to the PIO1. The PIO1 pin of the HM-10’s function is for a Connection Status LED. But one of the options one can set on the HM-10 is for the PIO1 to stay low unless the HM-10 has a connection. This can be set on the HM-10 when it’s in AT mode by typing:

  1. Type: AT+PIO11
  2. Response: OK+PIO11

When done, the ATtiny 85 will only power-up if the HM-10 has a connection. Of course, the solder-jumper is meant to bypass this feature.

The last solder jumper controls the HM-10’s reset. If soldered, the ATtiny 85 can reset the HM-10 by sending PB4 high for ~100mS. I added this as I hope to create a star-network with the ATtiny Bitsy Spider.

Here’s a summary explanation; the HM-10 has a time out feature after it losses connection from one HM-10 that prevents it from connecting to another for approximately 10 seconds. So far, there is no option to bypass this “lost connection” time-out. But resetting the HM-10 (<150mS power-cycle) bypasses this time-out. I’ll update more on this setup when I’ve completely tested it. If there are questions, I’ve written a lot in the comments of my original HM-10 post. But also feel fre to contact me.

One last thing I should mention.

I expect one major mistake and two minors on the first run of every board I send off. This board is no exception. I forgot the decoupling capacitors on the voltage regulator and the HM-10. I’ve added them on the v.02 board. Of course, this shouldn’t be a major flaw, but with a capacitor on the voltage regulator it causes it to spit out 3.6v instead of 3.3v. Major problem. I saved this set of boards by soldering a 0402 1uF between the legs of the SOT-23-5 regulator. Not fancy, but saved $5.

OLED via I2C

Originally posted on www.letsmakerobots.com

imagesI guess it’s been an I2C weekend. I found these organic light-emitting diode displays (OLED)images imagesat Itead studio for $5. images

imagesNifty little buggers.images

They might be small, but their extraordinary contrast and viewing angle more than make up for it. Plus, I mean, c’mon, they’re $5. I will say I was a little annoyed that they operate at 3.3v. And I’m sure this means I’ll be making a small little level converter board for them pretty soon. I estimate the converter board would be around $1.25, simagestill a good price.images

images imagesimagesSome perks of OLEDs:images

  1. imagesWider viewing angle (i.e., you don’t have to look straight down at it).images
  2. imagesNo back light, making them flatter and use less power (not a lot less).images
  3. imagesHigh refresh rate. The only time I saw a flicker is through my video camera. And I had delay(10); in my code :) images
  4. imagesThey are cheap(er?).images
  5. imagesThey’re the future :) images

The only downside that really jumped out at me was the libraries are about 9k flash uploaded. The 64x64 LMR Bot was around 1k.

imagesWhen I got them I was worried I wouldn’t be able to use them without digging into the datasheets. But come to find out, they were exactly the same unit as on Adafruit’s boards. Sorry, I love you Ada…but…can’t afford $19.50. Now, maybe if Becky Stern came with them. Erm. Anyway, with Ada’s excellent guides and software I had the LMR Bot moving around in about 10 minutes. So, I’ll end up buying something from Ada to monetarily say, “Thank you, love.”images

The connections go something like this:

  • imagesArduino Uno 3.3v <————> OLED VCCimages
  • imagesArduino Uno 3.3v <————> LV of Logic Converterimages
  • imagesArduino Uno 5v <————> HV of Logic Converterimages
  • imagesArduino Uno Gnd <——————> OLED GNDimages
  • imagesArduino Uno Gnd <——————> LV Logic Converter GNDimages
  • imagesArduino Uno Gnd <——————> HV Logic Converter GNDimages
  • imagesArduino Uno A5 (SCL) <——— Channel 1 Logic Converter ——–> OLED SCLimages
  • imagesArduino Uno A4 (SDA) <——— Channel 2 Logic Converter ——–> OLED SDAimages
  • imagesArduino Uno D4 (SCL) <——— Channel 3 Logic Converter ——–> OLED RESETimages

I know, I know; I’m working on a converter adapter to make tha all those wires go away.

imagesI’m real happy with these little boards :)images

ATtiny Adventure -- I2C on ATtiny 84/85

Originally posted on www.letsmakerobots.com

Code

UPDATE: Added info on making SPI programming jig (makes life a lot easier).

UPDATE: Added ATtiny 84 info (though, the post is meant for the ATtiny 85).

I’ve been non-traditional microcontroller curious for a bit. Then, I had to put a Digi-Key order together for some real cheap stupid stuff (some SOT-23 N-Channels for the LiPo charger circuit) and I thought, “What the hell, let’s order some ATTiny 85s.” Being cheap like I am, I ordered SMD:

I then ran over to OSHPark and made a little breakout for it:

This brought the price for one ATTiny 85 board to $1.53 each. This is great, since the ATTiny 85 has an internal oscillator up to 8mhz, allowing it run without any passives.

I was pretty excited the day they came in. I soldered them together, put some headers on them, and tossed them into a bread board. I switched over to Goggle and searched how to program these little guys. The first article I hit was the one I eventually used, I just warn you, dear reader, read careful not to miss the bit about ignoring the error. Personally, like the dumb-arse I am, programmed my first little ATtiny 85 a hundred times thinking it wasn’t working before I caught the caveat in the instructable:

“It should give the following error twice: avrdude: please define PAGEL and BS2 signals in the configuration file for part ATtiny 85”

This error means you programmed it successfully.

But you all probably got that.

The easiest way to get going with I2C with the ATtiny 85 is using the TinyWireS and TinyWireM libraries for Arduino.

  • TinyWireS (this is Rambo’s library, he updated the original with onRequest, onReceive functions)
  • TinyWireM

To get the ATtiny 84 to work you’ll need to add support:

They were developed to be comparable to the Wire library for Arduino. To install them, just unzip them and place them in your Arduino libraries folder (e.g., C:\Program Files\Arduino\libraries).

(Here’s the pinoutfor the ATtiny 84)

The I2C connections are pretty straight forward:

  • Arduino SDA <— 4.7k Resistor Tied to 5v —-> ATtiny 85 – PB0
  • Arduino SCL <— 4.7k Resistor Tied to 5v —-> ATtiny 85 – PB3
  • ATtiny 85 – PB1 <— 330 Resistor —- LED —- > GND

Below is code meant to demonstrate the purpose of this projects. It sets the ATtiny 85 as an I2C slave. It receives data over the I2C line, parses it into an integer, then writes this value of the integer to pin 1 (PB1).

// the 7-bit address (remember to change this when adapting this example)
#define I2C_SLAVE_ADDRESS 0x4

// Get this from https://github.com/rambo/TinyWire
#include <TinyWireS.h>

// The default buffer size, Can't recall the scope of defines right now
#ifndef TWI_RX_BUFFER_SIZE
#define TWI_RX_BUFFER_SIZE ( 16 )
#endif

//Character variable used to echo data back.
char chrSendData;

//Variables used in getting and parsing data.
char rxChrData; //Receives the data.
char rxString[12];  //Varbiable for holding one string of data.
int rxIndex = 0; //Used to index rxString.

//Integer for holding the pwm value received from master.
int pwmValA;

void requestEvent(){  
  TinyWireS.send(chrSendData);
}

//Handles receiving i2c data.
void receiveEvent(uint8_t howMany)
{
    if (TinyWireS.available()){  
      if (howMany < 1)
      {   // Sanity-check
          return;
      }
      if (howMany > TWI_RX_BUFFER_SIZE)
      {   // Also insane number
          return;
      }

      howMany--;
      if (!howMany)
      {   // This write was only to set the buffer for next read
          return;
      }
      while(howMany--)
      {   //Gets i2c data.
          rxChrData = TinyWireS.receive();
          //Places the characters in an array one at a time.
          rxString[rxIndex] = char(rxChrData);
          //Increment the data array.
          rxIndex++;
          //If a stop character is read, parse the char array and convert it to a single integer.  
          if (rxChrData == ':'){
              //This is a low memory form of parsing the char array into an intger
              pwmValA = int(100*rxString[2]+10*rxString[3]+rxString[4]);
              //Prints the parsed value.
              Serial.println(pwmValA);
              //Writes the parsed value to pin 1 (PB1).
              analogWrite(1, pwmValA);
              //Resets the char array index.
              rxIndex = 0;  
         }
      }
    }
}

void setup()
{
    Serial.begin(9600);
    pinMode(1, OUTPUT); // OC1A, also The only HW-PWM -pin supported by the tiny core analogWrite
    TinyWireS.begin(I2C_SLAVE_ADDRESS);
    //Sets up the onReceive function (what we do if we get stuff).
    TinyWireS.onReceive(receiveEvent);
    //Sets up the onRequest function (what we do if asked to send something).
    TinyWireS.onRequest(requestEvent);
}

void loop()
{
//Detects a stop sending command.
TinyWireS_stop_check();

//Puts the data we got into a variable to send back for error checking.
chrSendData = char(rxChrData);

}

I’ve also included the code I used on my Arduino Mega, which was setup as the master.

Your setup should not look like this :P

I’ve got several ideas I’d like to attempt with this setup. But, it is somewhat silly. The I2C reduces the ATtiny 85 to four pins. But one of those is the reset pin (PB5), so really, only 3 usable pins.

Before I started working with the Tiny I was lurking in the shoutbox and oversaw Protowrx chatting about making an ATtiny into a serially controlled motor driver. So, I set to it. I had chosen I2C because I wanted to make a setup like the DRV8830 (Spark fun has a breakout). Of course, like the numbskull I am I didn’t do the simple math before sinking hours into interfacing with a chip.

Most H-Bridge ICs require three pins a motor. Two digital pins for direction and one for PWM. Even cheaping out and using one PWM pin for both motors, that’s still five. _And…_the ATtiny 85 has 8 pins. 1 x Power, 1 x Ground, 2 x I2C line, which leaves us with….4 pins. Oh wait! One of those is the reset pin and cannot be used without losing the ability to program it without an AVR programmer (which I have, but what a pain in the ass). So! In short, there are 3 usable pins after interfacing with the ATtiny. I’d have done myself a favor if I had remembered an 80s classic.

Still, I’ve I got it in my head to attempt doing something like this: 2 Pin HBridge control. Only, tying the PWM line together. Not having much luck right now (only spent about 20 minutes, wanted to get this typed up before I forgot crap).

Another idea is to use a Software Serial to send one way communication through the serial line. But it doesn’t make much sense, since 4 pins aren’t much better than 3, given my intentions.

Ok. In conclusion, I’m not sure why I did this. It really doesn’t make much sense, other than the adventure. I’m sure it’s one of those things I work out now and I won’t find a use until much later. The real killer is thinking about how you can buy a full Arduino Pro Mini on the eBay for $3.45. A little more than double the cost of an ATtiny 85 but triple the pins and utility. Eh!

Making a ATtiny Jig:

I hate breadboarding. Let me admit that. Mainly, it is having wires everywhere, my little dyslexic brain can’t keep up. And when I first started working with the ATtiny uCs I found it to be a pain to have to move my little ATtiny’s between my full circuit and the SPI programming circuit. So, I thought, “Why not make a SMD programming pad and jig interface?”

Well, here is the crude son-of-a-bitch:

It’s nothing fancy, but it is a time saver.

I put both the interface pads and the jig in my Eagle library.

POGO_PIN_JIG_SPI

POGO_PIN_SPI_PAD

Ladvien’s Eagle Library

Here is my ATtiny 84 with the pads and the Jig PCB:

Jig ($.60

ATtiny 84 PCB ($1.85)

These are the pogo pins I used:

P100-B1 – 1.36mm diameter

It was not too hard to put together, I set it up something like this. Then, it is all about added flux to where the pins meet the PCB and soldering like you would usual header pins.

And here it is in action. It surprised the hell out of me, worked exactly like I wanted it.

I’m sure I’ll eventually add some stabilizer bars between the two-PCBs and maybe a guide pin to prevent me from pressing the pins in the wrong holes :(

Still, it is MUCH easier than pulling it from the breadboard and moving it to a new circuit. Makes me happy.

A Friendly Overlord

Originally posted on www.letsmakerobots.com

I’ve been working on this one in silence for a bit.

Awhile back it hit me, before I started growing my Overlord project in complexity I wanted to refine it for ease-of-use. Therefore, I began translating my Overlord project into a Python module I could build off.

A Friendly Overlord

I figure, this would make it easier for anyone to use. This includes myself, I’ve not forgotten my identity as a hack, nor will anyone who pops the hood on this module :)

But, at its core, there are few essential inputs:

  1. Color to track.
  2. Compass reading.

So, I spent some time translating the code into a callable module. This experiment was mainly for my own use, yet I knew it’d grow healthier if I had LMR’s feedback, elder or noob.

When I started I actually planned (gasp) out what would make this code more user friendly. I didn’t think long; the two things that have taken the most time tweaking to get this code useful are:

  1. Adjusting the compass heading.
  2. Selecting the color to track.

To address the first issue, I developed a “auto-compass calibration function.”

def mapper(x, in_min, in_max, out_min, out_max):
    #This will map numbers onto others.
    return ((x-in_min)*(out_max -out_min)/(in_max - in_min) + out_min)

def compass(headingDegrees):
    global compassInitFlag
    global initialRawHeading
    global intRx

    #This sets the first compass reading to our 0*.
    if compassInitFlag == False:
       initialRawHeading = headingDegrees
       compassInitFlag = True
       print initialRawHeading
       exit

    #This is the function that actually maps offsets the compass reading.
    global intialRawHeading
    if headingDegrees >= initialRawHeading:
        adjHeading = mapper(headingDegrees, initialRawHeading, 360, 0, (360-initialRawHeading))
    elif headingDegrees <= initialRawHeading:
        adjHeading = mapper(headingDegrees, 0, (initialRawHeading-1),(360-initialRawHeading), 360)

    #Here, our compass reading is loaded into intRx
    intRx = adjHeading

Basically, this function takes the very first compass reading and adjusts all other readings. So, all you have to do is put your robot in the direction you want it to consider “North,” start your code, and this function will convert all other readings.

The second issue took me a little longer to deal with: easy color selection. In short, I rewrote most of the color detection parts of the code to take advantage of the OpenCV’s CamShift algorithm. This function is more resilient to lighting changes or other near color objects, but it is also more CPU intensive. At some point, I’ll probably go back and write a variant that sticks with the old largest-target-color-mass method.

Ok, what this means for the user? When the code starts you select the color you’d like by left-click and dragging a selection box over an area. The mean color of the selected area will be tracked and this will also start the rest of the code.

What does Friendly Overlord give you?

Well, a lot. And when I finish writing the damn thing, more than alot.

Here’s a list, and only one bit is untrue.

  1. It tracks your robot, providing its x and y relative to your webcam.
  2. It will provide a target coordinates, which I’ll later make addressable in case someone wants to do something cool, rather than have their robot drive around and catch virtual dots. Lame.
  3. It will take the compass reading you provide, translate it to a heading relative to the camera, then, it will send commands to your robot telling it to turn until it is in alignment, then move towards the target.
  4. Make you a cuppa (CP, DanM, did I use that right?)
  5. It will allow you to tweak pretty much any element of the code (e.g., overlord.targetProximity = 5)

What does it not do?

  1. Take care of your serial data. You’re own your on, bud.
  2. Write your robot uC code for you.
  3. Provide you with your robot’s heading (though, when I delve into two-color detection this could be done with two-dots on your bot. But really, it’d be easier and near cheaper to get an HMC5883L).

Alright, so let’s talk code. How little code does it take to use it?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import serial
from time import sleep
import threading
import overlord

#Initialize Overlord variables.
overlord.dVariables()

#Open COM port to tether the bot.
ser = serial.Serial('COM34', 9600)

def OpenCV():
    #Execute the Overlord.
    overlord.otracker()

def rx():
    while(True):
        # Read the newest output from the Arduino
        if ser.readline() != "":
            rx = ser.readline()
            rx = rx[:3]
            rx = rx.strip()
            rx = rx.replace(".", "")
            #Here, you pass Overlord your raw compass data.  
            overlord.compass(int(rx))

def motorTimer():
    while(1):
        #This is for threading out the motor timer.  Allowing for control
        #over the motor burst duration.  There has to be both, something to write and
        #the motors can't be busy.
        if overlord.tranx_ready == True and overlord.motorBusy == False:
            ser.write(overlord.tranx)
            ser.flushOutput() #Clear the buffer?
            overlord.motorBusy = True
            overlord.tranx_ready = False
        if overlord.motorBusy == True:
            sleep(.2) #Sets the motor burst duration.
            ser.write(overlord.stop)
            sleep(.3) #Sets time inbetween motor bursts.
            overlord.motorBusy = False

#Threads OpenCV stuff.
OpenCV = threading.Thread(target=OpenCV)
OpenCV.start()

#Threads the serial functions.
rx = threading.Thread(target=rx)
rx.start()

#Threads the motor functions.
motorTimer = threading.Thread(target=motorTimer)
motorTimer.start()

This is fully functional code. You’ll notice that really, only about 10 lines get Friendly Overlord going, the rest handle Serial functions and motor firing. Be warned, the motor firing code will change, since it is written how I like it right now, eventually will be designed to be as flexible as possible.

Walkthrough:

  1. overlord.dVariables() #Sets the Friendly Overlord variables.
  2. overlord.otracker() # The module’s heart. Handles color tracking, angle calculation, etc.
  3. overlord.compass(x) # You pass it an compass heading as an integer in degrees (0-360) and it does the rest.
  4. overlord.tranx_ready # Simple flag to indicate last bit of serial data has be sent.
  5. overlord.tranx # Variable that contains the serial command to be sent to the robot.
  6. overlord.motorBusy # Flag to indicate if the robot is still in the middle of a movement.

That’s about it. In the module? 399 lines of code, or so. Still relatively small for a program but not something I want to wade through without a damned good reason.

Ok. So, where am I going with this?

Hell if I know. I want to make it as versatile as possible. Eventually, I’d like to be tracking nth number of robots. I envision a swarm of Yahmez’ Baby bots flying all over the place, Friendly Overlord tracking them, and communicating with them via IR.

But in the more immediate future, I’d like to make every variable tweakable. Especially, variables useful to others. For instance, the overlord.tX and overlord.tY are currently controlled by the module. They are simply randomized numbers. But, I’ll make a flag in the next two days to take control of them from your own code. You can decide where you’d like your robot to go. Whether it be to your mouse pointer (overlord.targetY = overlord.mouseY) or a complex set of way-points to lead him through a maze. Really, I’ll probably code around the feedback I get.

Now, some obligatory stuff.

Here are some of the current variables addressable from your program:

#How close to does the robot need to be? Greater is less accurate.
#Defaults to 5.
overlord.targetProximity = 5

#GUI X, Y
#Defaults to 0, 0
overlord.guiX = 440
overlord.guiY = 320

#Random target constraint; so target doesn't get placed too far from center.
#Defaults to 1, 640, 1, 480
overlord.targetLeftLimit = 20
overlord.targetRightLimit = 400
overlord.targetBottomLimit = 320
overlord.targetTopLimit = 20

But I’d like to make every variable needed by the user available.

Ok. So, here’s what I need: Someone to use it and provide feedback. I’m getting too close to it and bleary of thought.

I’ve thought of doing a few things to get some feedback:

  1. Setup a challenge (I’ve got some surplus).
  2. Offer to mail one person a month a setup (two Bluetooth PCBs and a cheap webcam).

Any suggestions?

I think I’ll make a walkthrough video pretty soon (kinda miss making stupid videos) but I’m a little worn out right now.

Homemade Pulse Sensor

Originally posted on www.letsmakerobots.com

I’ve been working on re-making the the Open Hardware Pulse Sensor so it’d be easy to send off to OSHPark and to make at home. I’m not sure, but I think I started this projects in March and I’ve just now finished it.

The bit of encouragement I needed was when hackaday.com put it up as their “Fail of the Week.” I thought I was going to be mature about it. But those four red letters started eating at me, so I gave it another go. Weirdly, I got it working.

I believe there were three problems:

  1. I had mixed up the op-amps again. In my defense, I’ve got 5 different ICs flying about in the same package as the op-amp.
  2. The Arduino I’d been plugging into was sitting on a surface that provided enough conductivity to create noise between the 3.3v pin on the underside and A0, which I was using for the op-amp in.
  3. Every time I touched the sensor the exposed vias were shorted through my own conductivity. Stupid mineral water.

** **

I’ve already detailed how I went about making it; so, I’ll try to stick to repeatability.

1. Order the parts.

  • Op-amp: .29 (Digi-Key)
  • Light Photo Sensor: 1.23 (Digi-Key)
  • LED: .79 (Digi-Key)
  • 0603 Schottky Diode: .50 (Digi-Key)
  • Passives: ~2.50 - Resistors: 1 x 470k, 1 x 12k, 2 x 100k, 1 x 10k, 1 x 3.3Meg - Capacitors: 3 x 4.7uF, 2 x 2.2uF
  • OSHPark Boards: **$.67 **(minimum 3 boards, costing $2.00. 3/2.00 = ~.67)

Total (approximate): $ 5.98

  1. Make sure you have theses tools.
  1. Solder the light-sensor.

The light sensor is the hardest bit, so take your time. I put a little bit of solder on each pad with my soldering-iron, then, cover the soldered pads in flux. Next, I attempt to align the light-sensor with the pads as close as possible. After, I put the board with the backside on an over-turned clothes iron. Let the iron heat up until the solder reflows and the sensor is attached.

  1. Flip the sensor and lock it to your surface with tacky-putty to solder the LED, passives, and op-amp. I won’t detail this, since my video shows the entire process.

  1. Wrap it with tape, cutting a small hole for the LED and light-sensor. (I’ll come up with a better solution, and a way it to clip it to your body, on the next iteration).

  2. **Wire it up to the Arduino **

Left —- Middle —- Right

A0 —— 3.3v ——–GND

  1. Run the Arduino and Processing sketches these amazing guys provided.

  2. Yell at me if you have problems.