Friday, February 20, 2015

Bash script for Cygwin to read in camera images from SD card

#this script does a nice job of reading in DCIM cards
#run with ./get_picts title
#it creates a folder with a date if the name is defaulted, appends drive name, then title.


#!/bin/bash
thisTitle=$*
getlabel() {
$(cygpath --sysdir)/cmd /c dir ${1}:\\ | \
    tr \\r \\n | \
    sed -n -e '1s/^ Volume in drive . is //p'
}

cd /cygdrive/c/DCIM
cd ~/DCIM
for i in e f g h i j k l m
#
#DIRS=`ls -d /media/matt/*/DCIM`
#echo $DIRS
#for thisTarget in $DIRS
do

    thisTarget="/cygdrive/${i}/DCIM"
    if [ -d "$thisTarget" ]; then
        driveName=`getlabel ${i}`
        echo  $driveName
        thisDate=$(date +%y%m%d)
        #echo $thisDate
        #echo $thisTitle
        thisDate=$thisDate"_"$driveName"_"$thisTitle
        echo $thisDate
        #read -p "Press [Enter] key to start copy..."

        if [ -d "$thisTarget/101ND610" ]; then
            mv "$thisTarget/101ND610" "$thisTarget/$thisDate"
        fi
        if [ -d "$thisTarget/101D3200" ]; then
            mv "$thisTarget/101D3200" "$thisTarget/$thisDate"
        fi
        if [ -d "$thisTarget/100D3200" ]; then
            mv "$thisTarget/100D3200" "$thisTarget/$thisDate"
        fi
        mv -f $thisTarget/1* .
        for jj in $(ls -d $thisTarget/* | xargs -n1 basename)
        do
            for kk in _1 _2 _3 _4 _5 _6 _7 _8
            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.%S%%-c '-filename<$CreateDate-$filenumber.%e' {} \;
find . -name "DSC*.NEF" -ls -exec exiftool  -d %Y.%m.%d-%H.%M.%S%%-c '-filename<$CreateDate-$filenumber.%e' {} \;
find . -name "IMG*.PEF" -ls -exec exiftool  -d %Y.%m.%d-%H.%M.%S%%-c '-filename<$CreateDate-$filenumber.%e' {} \;
find . -name "IMG*.PEF" -ls -exec exiftool  -d %Y.%m.%d-%H.%M.%S%%f%%-c '-filename<$CreateDate.%e' {} \;
find . -name "IMG*.CR2" -ls -exec exiftool  -d %Y.%m.%d-%H.%M.%S%%-c '-filename<$CreateDate-$filenumber.%e' {} \;
find . -name "IMG*.DNG" -ls -exec exiftool  -d %Y.%m.%d-%H.%M.%S%%-c '-filename<$CreateDate-$filenumber.%e' {} \;
find . -name "IMG*.DNG" -ls -exec exiftool  -d %Y.%m.%d-%H.%M.%S%%f%%-c '-filename<$CreateDate.%e' {} \;
find . -name "IMG*.JPG" -ls -exec exiftool  -d %Y.%m.%d-%H.%M.%S%%-c '-filename<$CreateDate-$filenumber.%e' {} \;
find . -name "IMG*.JPG" -ls -exec exiftool  -d %Y.%m.%d-%H.%M.%S%%f%%-c '-filename<$CreateDate.%e' {} \;
find . -name   "P*.JPG" -ls -exec exiftool  -d %Y.%m.%d-%H.%M.%S%%-c '-filename<$CreateDate-$filenumber.%e' {} \;
find . -name   "P*.JPG" -ls -exec exiftool  -d %Y.%m.%d-%H.%M.%S%%f%%-c '-filename<$CreateDate.%e' {} \;




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.