Thursday, October 31, 2013

Simple shell script to import photo's from SD card.



cd /cygdrive/c/DCIM
for i in e f g h i j k l m
do
thisTarget="/cygdrive/${i}/DCIM"
if [ -d "$thisTarget" ]; then
thisDate=$(date +%y%m%d)
if [ -d "$thisTarget/100ND610" ]; then
mv "$thisTarget/100ND610" "$thisTarget/$thisDate"
fi
mv -f $thisTarget/1* .
for jj in $(ls -d $thisTarget/* | xargs -n1 basename)
do
for kk in _1 _2 _3 _4
do
if [ -d $jj$kk ]; then
echo $jj$kk
else
mv -f $thisTarget/$jj  $jj$kk
break
fi
done
done
rmdir $thisTarget
fi
done
find . -type d -exec rmdir --ignore-fail-on-non-empty -p {} \;
find . -name "DSC*.JPG" -ls -exec exifautotran {} \;
find . -name "IMG*.JPG" -ls -exec exifautotran {} \;
find . -name "DSC*.JPG" -ls -exec exiftool  -d %Y.%m.%d-%H.%M%%-c.%%e "-filename<CreateDate" {} \;
find . -name "DSC*.NEF" -ls -exec exiftool  -d %Y.%m.%d-%H.%M%%-c.%%e "-filename<CreateDate" {} \;
find . -name "IMG*.PEF" -ls -exec exiftool  -d %Y.%m.%d-%H.%M%%-c.%%e "-filename<CreateDate" {} \;
find . -name "IMG*.CR2" -ls -exec exiftool  -d %Y.%m.%d-%H.%M%%-c.%%e "-filename<CreateDate" {} \;
find . -name "IMG*.DNG" -ls -exec exiftool  -d %Y.%m.%d-%H.%M%%-c.%%e "-filename<CreateDate" {} \;
find . -name "IMG*.JPG" -ls -exec exiftool  -d %Y.%m.%d-%H.%M%%-c.%%e "-filename<CreateDate" {} \;
find . -name "P*.JPG" -ls -exec exiftool  -d %Y.%m.%d-%H.%M%%-c.%%e "-filename<CreateDate" {} \;

Thursday, May 30, 2013

Solutions – performance

Performance tuning is some of the hardest software you will do.


Always try to test your system with as much fidelity as possible. 

      And allow multiple levels of simulation.

Before you ship, measure how much spare performance you have

      Leave most of the debugging in the “test” release to slow system down.

Common fixes to performance cause other problems

Caching – uses more memory
Looping – increases latency


Do performance fixes First & Last

i.e. design for performance, code for maintainability
Debug for performance only if you must.

Its ok to remove the debugging in the final version to provide some performance margin


Tuesday, April 23, 2013

Scooterputer schematic

I never did a layout, tried to keep it in my head.  When it was time to finish the project, I found that I didn't know where everything went.

I Used XCircuit to draw the layout.  It crashed a lot, but outputs to Postscript.
It made me realize that I have to be careful of the relays.  There is a setting that can cause direct battery to motor connection.

Saturday, March 2, 2013

Arduino Ethernet Relay Shield with Remote


Simple Ethernet Remote

This was a real quick project. I attached a relay shield and 315Mhz remote relay switch to the Seeeduino Ethernet to make a Ethernet remote control for lights and projector.



Future case, a dead ups

–Found two different programs, one very simple, one quite involved. Since this system only does lights (not security) I went with the simple one.
–Even so, there were problems with
           •Persistence, the gui did not read the state of the remote.
           •Did not support 8 relays (since the boards only have 4)
 –Used analog in as digital output
            •Crashed after a couple of commands.
–Just allocated more
            •Remote transmitter was not stable
–Used extra relay to power remote transmitter on and off


/*
    Web Server
 
 A simple web server that shows the value of the analog input pins.
 using an Arduino Wiznet Ethernet shield. 
 
 Circuit:
 * Seeedino Ethernet 
 
 created 18 Dec 2009
 by David A. Mellis
 modified 4 Sep 2010
 by Tom Igoe
 modified 20 Jan 2013
 */
 
#include <SPI.h>
#include <Ethernet.h>
 
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,0,177);
 
// Initialize the Ethernet server library
// with the IP address and port you want to use 
// (port 80 is default for HTTP):
EthernetServer server(80);
 #define  numPins 8
int pins[numPins+1] = { 4, 5, 6, 7,16,17,18,19,9};
int pinState[numPins+2] = {0};
char pinName[numPins][8]={
  "Reset",
  "Lite 1",
  "Lite 2",
  "Lite 3",
  "R1",
  "R2",
  "P1",
  "Power"
};
  
char line1[300];

void setup()
{
  for (int i = 0; i < numPins+1; i++)
  {
     pinMode(pins[i], OUTPUT);
  }
  digitalWrite(pins[numPins],0);
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.println("initialization done.");
}

void loop()
{
  EthernetClient client = server.available();
  if (client) 
  {
    while (client.connected()) 
    {
      readHeader(client);
      if (! pageNameIs("/"))
      {
        client.stop();  
        return;
      }
      client.println("HTTP/1.1 200 OK");
      client.println("Content-Type: text/html");
      client.println();

      // send the body
      client.println("<html><body>");
      client.println("<h1>Output Pins</h1>");
      client.println("<form method='GET'>");  
      setValuesFromParams();
      setPinStates();
      for (int i = 0; i < numPins; i++)
      {
         writeHTMLforPin(client, i);
      }
      client.println("<input type='submit' value='Update'/>");
      client.println("</form>");
      client.println("</body></html>");

      client.stop();            
    }
  }
}

void writeHTMLforPin(EthernetClient client, int i)
{
  client.print("<p>");
  client.print(pinName[i]);
//  client.print(pins[i]);  
  client.print("<select name='");
  client.print(i);
  client.println("'>");
  client.print("<option value='0'");
  if (pinState[i] == 0)
  {
    client.print(" selected");
  }
  client.println(">Off</option>");
  client.print("<option value='1'");
  if (pinState[i] == 1)
  {
    client.print(" selected");
  }
  client.println(">On</option>");
  client.println("</select></p>");  
}

void setPinStates()
{
  for (int i = 0; i < numPins; i++)
     digitalWrite(pins[i], pinState[i]);
  digitalWrite(pins[numPins],1);
  delay(300);
  digitalWrite(pins[numPins],0);
  if((pinState[numPins-1])||(pinState[numPins-2])||(pinState[0]))
  {
    pinState[0]=0;
    pinState[numPins-1]=0;
    pinState[numPins-2]=0;
    delay(300);
    for (int i = 0; i < numPins; i++)
       digitalWrite(pins[i], pinState[i]);
    digitalWrite(pins[numPins],1);
    delay(300);
    digitalWrite(pins[numPins],0);
  }
}

void setValuesFromParams()
{
  for (int i = 0; i < numPins; i++)
  {
    pinState[i] = valueOfParam(i + '0');
  }
}

void readHeader(EthernetClient client)
{
  // read first line of header
  char ch;
  int i = 0;
  while (ch != '\n')
  {
    if (client.available())
    {
      ch = client.read();
      line1[i] = ch;
      i ++;
    }
  }
  line1[i] = '\0'; 
  Serial.println(line1);
}

boolean pageNameIs(char* name)
{
   // page name starts at char pos 4
   // ends with space
   int i = 4;
   char ch = line1[i];
   while (ch != ' ' && ch != '\n' && ch != '?')
   {
     if (name[i-4] != line1[i])
     {
       return false;
     }
     i++;
     ch = line1[i];
   }
   return true;
}

int valueOfParam(char param)
{
  for (int i = 0; i < strlen(line1); i++)
  {
    if (line1[i] == param && line1[i+1] == '=')
    {
      return (line1[i+2] - '0');
    }
  }
  return pinState[param-'0'];
}

 


Sunday, January 27, 2013

ScooterPuter Integration

When I went to put everything together, the display code turned out to still hog too much latency and cpu.  So very quickly I found that I needed to lower the priority of the display code.

After that I tested the whole thing, and it did not have as much power as the old controller had.  The issue is that the PWM Amp would turn off fairly quickly at full power (i.e. before the scooter could even get up to speed).


I had selected 30a 24v dual half-bridge PWM Amp, which seems like plenty.  However 1st pass did not have enough power transferred to the motor.
Some measurements indicated that the motor was lower resistance than expected, and run at a much lower voltage than expected.  So 400w (the motor size) is 40a @ 10v, but 80a @ 5v for low speed operation (since back EMF raises the voltage).

Rewiring for second pass allowed contacts to touch causing 1 pwm amp to explode.  (audible pop, magic smoke escaped).  I realized I could use ½ bridge instead of full bridge to double the power, then add the third ½ bridge for 3x the current of the original system.   70a should allow for plenty of power


After everything worked there was still the issue of putting it all tightly together.  Although everything was tightly packed, there was so little space for wire bends that it created stress on the system.
System was sufficiently complicated that it took a couple of hours to remember what did what, so final packaging awaits more time.


Result
Latency (caused by display) stays under 100ms in all cases.  This limits ability for digital current limiting, but the PWM Amp is supposed to do this anyway.  To limit current, I added software smoothing of voltage command.  This caused smoother accelerations and limited large current surges.


ScooterPuter Software Development




Since I knew this would take a lot of work, first I built a hardware in the loop simulator.

I used Proto Shield for the leds, pots resistors etc.
Add all the Analog Inputs necessary
Speed control
Tortoise/Rabbit control- moderates speed control for indoor vs outdoor use.
Use LED’s for information
Power +
Power –
Loop timing

This allowed me to get all of the code working without blowing anything up.
I also took the time to setup configuration control.

I used TortoiseSVN & ssh & existing Ubuntu server.  Took a bit to setup, but works.
Allows use of throw-away code.  I Checked in each working change, then I try new ideas and throw it away if it doesn't work.

However, it turns out its easier to check into Google code than you own Ubuntu server!


Right away I ran into problems with the Display Shield.  It was meant for pretty graphics, not useful work.  I had to write my own 7 segment display.

I also found out that the driver code for the display locks out interrupts way to long.  It was bad enough, it affected the HIL simulator.  It also affected the A/D converter.  I tweaked the driver code to minimize the lock-out time.  I tried various other tricks (like nested interrupts) but the Arduino did not support them. 


 

ScooterPuter Design Notes

Just the notes please....

Seeeduino Mega
I chose the Seeeduino Mega because I was concerned about how much I/O the base model had.  It turned out this was a great choice because the base model is really limited.


Compatible with Arduino shields.
Has tons more digital output/input lines
Easy to control more than one shield.
Has 4x memory (128k vs 32k)
Real application has a lot more code than “demo” app.

Even doing a simple project, like my remote/relay project, you run out of I/O.  With the mega there is so much I/O that its no problem.  Turns out that the extra PWM out really makes a difference.

Arduino's use PWM for any output, and also for periodic tasks.  If you want a "fine" control you have to tweak the PWM.  Since the PWM timers are also used for the delay, this quickly becomes a problem.

Not a problem with the Mega, it has more of everything.


Display Shield
Color LCD display
Comes with software
Just remapped pins (because its Shield #2) and it worked.
A lot of fairly difficult soldering (has a bunch of really fine pitched soldering).
But worked 1st time
Shield did not have pass-through (for stacking) but was kit, so it was easy to just use the right connectors.
http://www.nkcelectronics.com/rgb-lcd-shield-for-arduino-65k-color-k65.html


Proto Board
Comes with stacking sockets (some of which I used for other Shields)
Use proto board to remap pins to allow Relay Shield to stack on top of display shield.
Proto board also drove the external PWM amp
Used proto board for system simulator.

Motor PWM Amplifier
Used Robot Power 30a Simple-H PWM Amp
Robot Power specializes in PWM Amps for combat robots.  (These motors are similar in size to the 400w mobility motors).
400w motor, is 20a @ 20v
Board has two half bridges
Because Combat Robots reverse directions rapidly.


Relay Shield
Cheap and really isolates output.
Has limitation of slow switching (vs ssr)
Board layout not rigged for stacked shields
What's with this?  Relay board uses only most of the Digital I/O.  Have to de-solder the stacked pins (some 30 pins) and replace with sockets.  Also have to tie power to Arduino bus.
For so much time saving, its very cost effective.



Sunday, January 20, 2013

ScooterPuter

Mobility Scooter

I end up spending a lot of time fixing Mobility scooters.  In part because I could (I had worked for a year on motor controllers), in part because I could use the result.  The biggest benefit was a substantially increased understanding of how they work

Here are some pictures:
The HIL simulator:

The pre-packing project:

Parts:
Seeeduino Mega ($43)
Relay shield ($20)
RGB LCD Shield for Arduino 65K color KIT($20)
RobotPower Simple-h Bridge ($50)

source:
http://code.google.com/p/scooterputer/