Monday, June 3, 2013

EnkiduBot v0.2

Time flies when you ignore it. 6 months have passed since I've worked on my EnkiduBot, the self-driving RC car system I'm developing. Here I'm sharing my 2nd video, with the progress I visualized in November but I am still realizing.


Here I explain some of the basics, and you actually get to see me improve the code, upload it to the onboard processor, and you even get to see the results. Obviously, there's a lot to be done before this is ready for retail, but I'm confident that the next 12 months will deliver good results, as long as I stay focused on this project instead of being distracted by a Plan B project.

Update: Source Code and Hardware Layout


I don't have a drawing of the connections between the Arduino, its Motor Shield, the Parallax Ultrasonic Distance Sensor, the RC car's plastic frame and electric motors, nor the 2 sets of battery connections. Schematics will be on their way tomorrow, thanks to Fritzing.

In the meantime, I will at least provide a list of what's connected where, so it's at least recorded somewhere. To begin, I'm using a Jeep Rubicon-branded RC car frame, produced by New Bright. Almost any RC car chassis would work, but this one is large enough that it can't move very fast, even at maximum power. This means usually nothing breaks when it runs into the wall. One unusual feature of this particular RC car is that the steering is controlled by an electric motor instead of an electric servo. This will complicate programming the steering function somewhat. I have stripped the electronics board from the frame where it sat behind the speaker. I left the front (steering) and rear motors, and the speaker which is too well glued to the plastic chassis to remove without serious damage.

On the white plugboard, I have a rather complicated wire setup, which is to simplify setting up 4 ultrasonic distance sensors, for front, rear, left, and right. Each sensor requires power and ground, and the one in this example has a 3rd pin for data. The other sensors I'm using have another pin for data because they are an older, cheaper model I found online. To simplify, the sensor I'm using faces forward on the frame, gets its power from the 5v Arduino pin, has its GND pin connected to the Arduino GND pin, and the DATA pin connected to Arduino pin 7. This is identical to the layout for the Arduino Ping example.

Early in this project, out of ignorance, I uncoupled the Motor Shield's power line from the Arduino power line. I thought this was necessary to protect the Arduino's processor, but it's not, as the ATMega168 can apparently convert 19v down to 5v. But this modification is optional and sometimes recommended, and it means I can disconnect the motor batteries and just work on the software and sensors.

I've connected the rear motor to the Motor Shield screw terminal block A, and the front steering motor to block B. There's a detachable 8-AA battery holder attached to the screw terminal block, with negative to GND and positive to VIN, which provides 12v to the motors. Instead of varying the amount of voltage or amperage going to a motor, The Motor Shield's relays instead give full power for fractions of a second -- this is called Pulse Width Modulation (PWM), and means you can power the motor for just 1/256th of a second, if you wanted.

Now, for the code:

const int motorApwm = 3; // Motor A output pin (hardwired on motor shield)
const int pingPin = 7;     // pin used by the PING sensor
const int motorBbrk = 8; // Motor B brake pin (hardwired on motor shield)
const int motorAbrk = 9; // Motor A brake pin (hardwired on motor shield)
const int motorBpwm = 11; // Motor B output pin (hardwired on motor shield)
const int motorAdir = 12; // Motor A direction pin (hardwired on motor shield)
const int motorBdir = 13; // Motor B direction pin (hardwired on motor shield)
const int motorAsns = A0; // Motor A sensor pin (hardwired on motor shield)
const int motorBsns = A1; // Motor B sensor pin (hardwired on motor shield)

int brakeAHigh = LOW; // turn off the parking brake
int pwmAspeed = 0; // set motor speed to 0/255
int dirALowForward = LOW; // Which direction the motor should spin
                          //LOW = forward, HIGH = reverse

int brakeBHigh = LOW; // turn off the steering lock
int pwmBturn = 0;    // set steering motor speed to 0
int dirBLowLeft = LOW; // Which direction the motor should spin
                      //LOW = left?, HIGH = right?

long lastCm = 14;  // Used for speedometer
long carSpeed = 0; // Used for speedometer


void setup() {
  //Set up the motors for the correct outputs
  pinMode(motorAdir, OUTPUT); 
  pinMode(motorApwm, OUTPUT);
  pinMode(motorAbrk, OUTPUT);
  pinMode(motorAsns, INPUT);
  pinMode(motorBdir, OUTPUT);
  pinMode(motorBpwm, OUTPUT);
  pinMode(motorBbrk, OUTPUT);
  pinMode(motorBsns, INPUT);
  pinMode(buttonPin, INPUT);
   
  Serial.begin(9600); // To see the values on the PC
}

void loop() {
long duration, inches, cm; // These 3 variables are used for the 
                            // Distance sensor's math functions below

  digitalWrite(motorAdir, dirALowForward); // Tell Motor A to go forward or reverse
  digitalWrite(motorAbrk, brakeAHigh);     // Apply or release Motor A's brakes
  digitalWrite(motorBdir, dirBLowLeft);   // Tell Motor B to turn left or right
  digitalWrite(motorBbrk, brakeBHigh);    // Apply or release Motor B's steering brakes
  
  
  // copied from ultrasonic_range
  pinMode(pingPin, OUTPUT);   // Set the Ping pin to Send
  digitalWrite(pingPin, LOW); // Clear the line to the sensor
  delayMicroseconds(2);       // wait 0.002 seconds
  digitalWrite(pingPin, HIGH); // send the ping
  delayMicroseconds(5);        // wait 0.005 seconds
  digitalWrite(pingPin, LOW); // Clear the line to the sensor
                              // We sent that ping 0.007 seconds ago
  pinMode(pingPin, INPUT);    // Set the Ping pin to Receive
  duration = pulseIn(pingPin, HIGH); // set the variable named Duration
                              // to be the number of microseconds until
                              // the ultrasonic ping comes back

  inches = microsecondsToInches(duration); // Calls the function that converts microseconds to inches
  cm = microsecondsToCentimeters(duration);// Calls the function that converts microseconds to centimeters
  carSpeed = lastCm - cm; //Speedometer. Sets carSpeed to be the previous distance minus the current distance to the wall. 
  lastCm = cm; // Replaces the previous distance to wall with current distance to wall.
  
  // Depending on the distance and car speed, speed up or slow down
 if (cm>30){ 
    if (carSpeed<20){
     if  (pwmAspeed < 128) {
       pwmAspeed += 10;
   }
     dirALowForward = LOW;
     brakeAHigh = LOW; 
   }else if (carSpeed>20){
     if  (pwmAspeed > 15) {
       pwmAspeed -= 10;
   } 
     dirALowForward = LOW;
     brakeAHigh = LOW; 
  }
 }else if (cm>1000){ 
    if (carSpeed<20){
     if  (pwmAspeed < 245) {
       pwmAspeed += 20;
   }
     dirALowForward = LOW;
     brakeAHigh = LOW; 
   }else if (carSpeed>20){
     if  (pwmAspeed > 5) {
       pwmAspeed -= 20;
   } 
     dirALowForward = LOW;
     brakeAHigh = LOW; 
  }
 } else { // if we're closer than 30cm
    if (carSpeed<20){
     if  (pwmAspeed < 128) {
       pwmAspeed += 5;
   }
     dirALowForward = HIGH; // reverse
     brakeAHigh = LOW; 
   }else if (carSpeed>20){
     if  (pwmAspeed < 128) {
       pwmAspeed += 5;
   }
     dirALowForward = HIGH; // reverse
     brakeAHigh = HIGH;  // brakes on
  } 
}
  if (pwmAspeed > 255) {
  pwmAspeed = 255; // Makes sure we never give more than 100%
}

  //Debugging output, so we can see these values in real time on the PC  
  Serial.print(inches);
  Serial.print(" in, ");
  Serial.print(cm);
  Serial.print(" cm, ");
  Serial.print(lastCm);
  Serial.print(" lastcm, ");
  Serial.print(carSpeed);
  Serial.print(" car speed, ");
  Serial.print(pwmAspeed);
  Serial.print(" pwmAspeed, ");
  Serial.print(dirALowForward);
  Serial.println();
  
  analogWrite(motorApwm, pwmAspeed); // Power the motor at the speed set above
  digitalWrite(motorAbrk, brakeAHigh); // Apply the brake, or don't. I have this twice, might remove one.
  
    delay(100); // Wait 0.1s, which is necessary for ultrasonic ping operation. Depending on the amount of code, this should be reduced.
}
    

// Sound moves 1 inch every 74 microseconds. Divide by 2 to remove the sound's return distance
long microsecondsToInches(long microseconds) 
{                                            
  return microseconds / 74 / 2;
}

// Sound moves 1 centimeter every 29 microseconds. Divide by 2 to remove the sound's return distance
long microsecondsToCentimeters(long microseconds) 
{                                            
  return microseconds / 29 / 2;
}
---

If you look closely, you can see where I changed the distance in the video, from 10cm to 30cm. I'm still fine-tuning the acceleration and deceleration curves. I want to start recording the speed and distance in a file on the SD Card shield, but pins 11, 12 & 13 would then be in use for too many devices.


Update 2: Breadboard and Schematic views


Here are the images for which you've all been eagerly awaiting -- my breadboard  and schematic images. Fritzing makes this as easy as laying out an office in Visio, or maybe easier. First, the breadboard image. 

My Arduino configuration. 

In this image, you see a breadboard with an ultrasonic sensor, the Motor Shield atop the Arduino, a 9V battery powering the Arduino, and a 12V 8-AA battery pack powering the Motor Shield, which powers the electric motor. Essentially, I can disconnect and detangle this setup from this RC car frame, and attach it to any other RC car, to make it self-driving.


Schematic drawing of Arduino and Motor shields
with sensor, motor, and batteries

In this drawing, you see more clearly that there are only a few wires to be connected, and most of those are moving power from one component to another. If the Motor Shield VIN were not severed, the Arduino could probably run off the 12V power supply to reduce complexity. But that leads to the possibility of the Arduino processor running out of power if the motor were drawing too much. As I said above, the 2-battery setup has advantages and disadvantages. Also, the 9V battery could be replaced with any USB charger, including a large USB battery pack I also own. 


If you have any ideas, suggestions, improvements, or criticisms, please comment.

Sunday, May 5, 2013

Sunday Update

Spark Core

Last week, Spark Devices launched the Spark Core on Kickstarter. This Arduino-powered, wifi-cloud-connected development device is designed exactly to make easier projects like mine. The Spark Core obviates my need to use Xbees, as the Core is exactly what I was trying to make, but better. I believe they beat me to it because their team has 4 members, while mine has just me.

The Kickstarter page shows a Twitter refrigerator magnet. My visualized refrigerator monitor would be pretty much that, but displaying temperature instead, with another wire running to the sensor placed within the refrigerator. It would also have an SD card inside, recording temperatures for long-term compliance or analysis.

LCD Screen

I assembled my LCD shield. Unfortunately it doesn't work. Soldering on breadbords is tricky and I'm not quite as skilled in EE as I like to believe. I didn't perform incoming QA on the LCD screen, so I don't know if the screen worked before I assembled it onto my LCD shield. Or it could have been a wiring mistake I made. Either way, I wanted to share some of the considerations I had when wiring it:

Atmel's ATMEGA168 only has 28 pins, of which only 13 are set up for digital output. Yes, you can modify the 5 analog input pins for digital output in software, but combining these 3 devices won't require that many.

Digital Pins

0
1
2
3
4
5
6
7
8
9
10
11
12
13


Wireless SD Shield: Working with this shield and the Xbee, I've come to understand that the shield uses SPI to allow the shield to work with both the wireless radio and the SD card without taking up 6 to 8 Arduino pins. Both the wireless radio and SD card use Arduino pins 11, 12, and 13 for communication. Pin 4 is used by the Arduino (the master device) to select the SD card as the subordinate device on the SPI bus, while pin 10 is used to signal that the wireless radio port is the subordinate with which the master device is communicating over the SPI bus (on pins 11, 12 and 13).


Digital Pins - Wireless SD Shield

0
1
2
3
4 SD select
5
6
7
8
9
10 Xbee Select
11 SPI MOSI
12 SPI MISO
13 SPI Clock



DHT11: Using this blog as my lab workbook means I don't have to relearn how a component works. This device won't even take up a digital pin -- its library automatically runs the single analog pin needed by the sensor.

LCD Shield: Controlling an HD44870 requires 6 pins - 1 for RS (Register Select), 1 for Enable, and 4 for data. The Arduino LiquidCrystal tutorial uses pins 2, 3, 4 & 5 for data, 11 for Enable, and 12 for RS.


Digital Pins - LCD Shield

0
1
2 D7 - LCD pin 14
3 D6 - LCD pin 13
4 D5 - LCD pin 12
5 D4 - LCD pin 11
6
7
8
9
10
11 Enable - LCD pin 6
12 RS - LCD pin 4
13



This presents a problem, as we're already using pins 4, 11 & 12 for the Wireless SD Shield.


Digital Pins - LCD Shield & Wireless SD Shield
0
1
2 D7 - LCD pin 14
3 D6 - LCD pin 13
4 D5 - LCD pin 12 & SD select
5 D4 - LCD pin 11
6
7
8
9
10 Xbee Select
11 SPI MOSI & Enable - LCD pin 6
12 SPI MISO & RS - LCD pin 4
13 SPI Clock



So I relocated the LCD pins to 2 & 3 for Enable & RS and 5, 6, 8 & 9 for data.

Digital Pins - revised LCD Shield & Wireless SD Shield
0
1
2 LCD Shield - RS - LCD4
3 LCD Shield - Enable - LCD6
4 SD Shield - SD select
5 LCD Shield - D4 - LCD11
6 LCD Shield - D5 - LCD12
7
8 LCD Shield - D6 - LCD13
9 LCD Shield - D7 - LCD14
10 SD Shield - Xbee Select
11 SD Shield - MOSI
12 SD Shield - MISO
13 SD Shield - Clock



Wednesday, May 1, 2013

Hardware Startups

Chris Dixon makes some great points in this post about the changing landscape of starting a company that sells electronics devices.


Slight Pivot

Wifi Website Controls for Arduino


One of my goals for this project was to have a website interface displaying temperature stats, available over wifi. I know this can be done, but I'm starting to think my Minimum Viable Product isn't Minimal enough. And, like others have said, a lot of people would like a simple LCD display showing their refrigerator's current temperature. So, I'm going to move the Wifi-website part of this project aside, and put in an LCD screen.

That said, the entire device is now made of pieces with which I've worked previously: Arduino Uno, SD card on Wireless SD shield, clone of HD44870 lcd display & DHT11 temperature sensor. Since I previously burned out my HD44870, I'll be assembling another one. This time, I've decided to attach the HD44870 onto a blank Arduino shield. I will have the shield soldered together today, and might get code onto it!

---

Thanks, seancneal, for suggesting another address to try with my Sainsmart LCD screen. Honestly, I'd kinda forgotten about that screen. I'll try this address and post an update.

Monday, April 29, 2013

MSP TryFi Prep

Today, I'm going to begin merging 2 disparate devices. We're going to start "pre-marriage counseling" for a union between 2 devices which can talk to each other, but aren't really intended to.

Bride and Groom



Our goal is to get the MSP-430 and the Xbee Wi-Fi radio to communicate. If we can have it report available networks over a serial connection, then it can host a webpage over wifi. To make this happen, we'll need to do several things:



1. Install CJBearman's XbeeWifi library into Energia
2. Make an SPI connection from the MSP to the Xbee -- 4 pins plus VCC (power) and ground
3. Make another connection for XbeeWifi library's 4 required pins
4. Transfer and run code






Sunday, April 28, 2013

Sunday Update

New Look!

I like orange!

New Inspiration

After re-reading CJBearmans documentation, I better understand the challenges with this project. I'm on the right track, as the library needs 3 more digital pins to better control the Xbee. (I wound up using Arduino Pin 5 for RESET, Pin 6 for ATN, and Pin 8 for DOUT.) Since the Xbee's designed to run at 3.3v and my Arduino Uno uses 5v, I believe I may have fried this Xbee radio.

Some drunken fool (possibly myself) scribbled out an idea on my whiteboard last night. I was eventually going to see if a TI MSP430 could handle both hosting a webpage and running an Xbee, but only after I got it all working on the Arduino. The MSP430 is a much smaller, cheaper development kit than the Arduino Uno, and its 3.3v processors run much slower -- 12MHz (or even 1Mhz) vs the 80Mhz processor in the Uno. But the processors cost about 1/10th as much as the Atmel processors inside the Arduino Uno, which is important for production. And someone has created Energia, an open-source copycat of the open-source Arduino compiler -- meaning we can literally run the same code on both processors. This means I can take all of the code with which I've been working on the Arduino and simply keep working in Energia (after importing CJBearmans XbeeWifi library into the other program)

So tomorrow I'll again be "Frankensteining" together 2 devices that aren't designed to work together. Isn't development fun?!?

Kickstarter

One main goal of this project has been to crowdfund with Kickstarter to start a (small or large) company.  I will have more information about this part of the project later this week.

GilgaTech

I've always planned for this page to be a workshop notebook, mainly focused on this company I'm learning to build. I've decided to launch Gilgamech's Technologies for my more general-purpose technology thoughts and pursuits.

Wednesday, April 24, 2013

TryFi 4

TryFi 4 - The SPI Try

I've been trying to line up which pins to provide the XbeeWifi library, so it can communicate with the Xbee wifi radio. Once I have this completed, it should be somewhat easier to make it host a webpage over the wifi connection.

Let's go over what I have learned so far:
*SPI uses 5 pins to communicate:
  -MOSI = Master device (Output) to the Subordinate device (Input)

  -MISO = Master device (Input) from the Subordinate device (Output). Named after a tasty soup, this is opposite of MOSI.
  -CLK = Clock. It's a circuit in a processor that's like a camshaft in an engine, in that it synchronizes all of the other parts. One master device can provide the clock signal to multiple subordinate devices.
  -ATN =Attention This allows a subordinate device to tell the master device that it has information to send. 
  -SEL = Select. This pin is used by the master device to tell a subordinate device to transmit data. This allows designs where MOSI, MISO, and CLK are shared between several subordinate devices, and each subordinate will only use the MOSI and MISO lines (also known as a Bus) when their SEL is turned on during the CLK pulse. This would save pins, allowing more subordinates per master. 

*CJBearman's XbeeWifi library calls for 3 of these plus 1 additional pin:
  -RESET - Reset. This is optional, but allows for the Xbee to be reset into SPI mode by the library. The other option is to manually configure the Xbee with X-CTU.

*The Xbee uses the following pinouts:

  -MOSI = 11

  -MISO = 4

  -CLK = 18

  -ATN = 13

  -SEL = 17
  -RESET = 5

*Arduino Uno SPI pinouts:
  -MOSI = 11 & ICSP 4

  -MISO = 12 & ICSP 1

  -CLK = SCK = 13 & ICSP 3

  -ATN = 

  -SEL = 10 (SS)
  -RESET = 1 & ICSP 5

Something to note here is the Arduino Uno's ICSP header has these same pins -- it seems pin 11 and ICSP 4 both connect to the same pin on the Atmel ATMega328. A good post with some very technical details helps me to sort this out. I'm not completely sure that Reset on the Uno is the same Reset as the Xbee is looking for. 

So far, we have:
Select: 10
Atn: ? 
Reset: 1?
DOUT: 12

For the library to work, we have to have at least the first 2 filled in. Out of desperation, I'm manually wiring the Reset and ATN pins to 5 and 6

Here the yellow wire runs from Arduino
Pin 5 to Xbee pin 5, while the white wire
runs from Arduino Pin 6 to Xbee Pin 17 

Looking at the pinouts...