Less Flimsy Arduino Ocelli

https://gist.github.com/3968902

/*
  Less Flimsy Arduino Ocelli

  Get the direction of the source of light from three photoresistors.

  Andrej Primc <aprimc@gmail.com> (http://fgh.si)

*/


int getSource(int a, int b, int c, int bins = 24) {
  int ab = abs(a - b);
  int bc = abs(b - c);
  int ca = abs(c - a);
  int mul = bins / 6;
  int h;
  int m;

  if (a > b && b >= c) {
    h = 0;
    m = mul * 2 * bc / (ca + bc);
  } else if (b >= a && a > c) {
    h = 1;
    m = mul * 2 * ab / (bc + ab);
  } else if (b > c && c >= a) {
    h = 2;
    m = mul * 2 * ca / (ab + ca);
  } else if (c >= b && b > a) {
    h = 3;
    m = mul * 2 * bc / (ca + bc);
  } else if (c > a && a >= b) {
    h = 4;
    m = mul * 2 * ab / (bc + ab);
  } else if (a >= c && c > b) {
    h = 5;
    m = mul * 2 * ca / (ab + ca);
  } else {
    h = 0;
    m = 0;
  }
  return h * mul + m;
}


void setup() {
  Serial.begin(9600);
}


void loop() {
  int a, b, c, h;
  a = analogRead(A0);
  b = analogRead(A1);
  c = analogRead(A2);
  h = getSource(a, b, c);

  Serial.print(h);
  Serial.println("");

  delay(1000);
}

Flimsy Arduino Ocelli

EDIT: don’t use this, use less flimsy arduino ocelli instead

Get the direction of the source of light from three photoresistors and present it as a number on a clock dial.

Inspired by the bees.

https://gist.github.com/3966275

/*
  Flimsy Arduino Ocelli

  Get the direction of the source of light from three photoresistors and
  present it as a number on a clock dial.

  Andrej Primc <aprimc@gmail.com> (http://fgh.si) inspired by the bees

  There are three ocelli facing directions 12, 4 and 8 on a clock dial. If
  all three ocelli are receiving about the same amount of light, the source
  is above (0). If ocellus facing 12 receives most light and ocelli facing 4
  and 8 about the same, the light source is 12. If ocellus 12 receives more
  than ocellus 4 and ocellus 4 more than ocellus 8, the light source is 1.
  And so on.

  Sensor readings will more often be unequal than equal. Unless we round the
  readings using some constant K, even positions, where we test for equality,
  will cover less of our imaginary dial then odd positions, where we test
  for inequality.

  The right K is a mystery. If it's too low, we'll get mostly odd positions.
  If it's too high, we'll get mostly even positions. If it's even higher than
  that, we'll get mostly "above".

*/

const int sensor_pin_a = A0;  // facing 12 o'clock, i.e. front
const int sensor_pin_b = A1;  // facing 4 o'clock
const int sensor_pin_c = A2;  // facing 8 o'clock
int K = 64;  // constant that defines "about the same"


void setup() {
  // used by utility flashBits(int)
  pinMode(13, OUTPUT);  
}


// utility: flash pin 13 with a binary representation of d
void flashBits(int d) {
  boolean flag = false;
  for (int i = 15; i >=0 ; i--) {
    if ((1 << i) & d) {
      // long pulse means 1
      flag = true;
      delay(50);
      digitalWrite(13, HIGH);
      delay(400);
      digitalWrite(13, LOW);
      delay(50);
    } else {
      //short pulse means 0
      if ((!flag) && (i != 0)) {
        // skip leading zeroes
        continue;
      }
      delay(225);
      digitalWrite(13, HIGH);
      delay(50);
      digitalWrite(13, LOW);
      delay(225);
    }
  }
  delay(500);
}


void loop() {
  int a, b, c;
  int source;

  // read sensors
  // A is at 12 o'clock
  // B is at 4 o'clock
  // C is at 8 o'clock
  a = analogRead(sensor_pin_a) / K;
  b = analogRead(sensor_pin_b) / K;
  c = analogRead(sensor_pin_c) / K;

  // get direction
  // 1 - 12 are positions on a dial, 0 is above (or below)
  if (a == b) {
    if (b == c) {
      source = 0;  // above
    } else if (a > c) {
      source = 2;
    } else {
      source = 8;
    }
  } else if (b == c) {
    if (a > b) {
      source = 12;
    } else {
      source = 6;
    }
  } else if (a == c) {
    if (a > b) {
      source = 10;
    } else {
      source = 4;
    }
  } else if (a > b && a > c) {
    if (b > c) {
      source = 1;
    } else {
      source = 11;
    }
  } else if (b > a && b > c) {
    if (a > c) {
      source = 3;
    } else {
      source = 5;
    }
  } else { // c > a && c > b
    if (a > b) {
      source = 9;
    } else {
      source = 7;
    }
  }

  // flash position on led 13
  flashBits(source);

  delay(1000);
}

Packrat parser for Python

I found this in my files. I can’t remember what I wanted to do with it.

Get it here: https://gist.github.com/3789707

The great idea is someone elses and I can’t find the link. Really! Google and Wikipedia are not my friends today. The kewords used to be “packrat parser” and “memoization”.

See Packrat Parsing: a Practical Linear-Time Algorithm with Backtracking.

The great problem is this: bottom-up generates too many results, top-down with backtracking generates the same results too may times.

The great solution is to do top-down and remember the results.

The remaining problem is how to handle left recursion.

The code solves some problems, but not all.

robots.txt parser for Erlang

I couldn’t find a robots.txt parser for Erlang, so I wrote my own. If it sucks, it’s because it’s my “Hello world” in Erlang. :)

Get it here: https://gist.github.com/3789675

It requires mochiweb_util.erl for parsing URLs.

Use it like this:

Eshell V5.7.4  (abort with ^G)
1> O = robots_txt:parse("# comment\n\nUser-agent: foo\nDisallow: /\n\nUser-agent: *\nDisallow:").
[{'User-agent',"foo"},
 {'Disallow',"/"},
 {'User-agent',"*"},
 {'Disallow',[]}]
2> robots_txt:is_allowed("foo", "/bar", O).
false
3> robots_txt:is_allowed("baz", "/bar", O).
true
4> 

It handles only the “User-agent” and “Disallow” directives. It ignores the “Allow” directive.

It makes its decision on the first matching directive. It assumes that specific rules precede the generic ones. That is what Wikipedia and Facebook assume as well. Google, as a server, doesn’t.

It shouldn’t crash on junk.

It is inspired by Python’s robotparser, but it doesn’t insist on fetching the file itself.

Circadian clock for Arduino

Circadian clock for Arduino sets its time by observing dusk and dawn. Once it’s set, it shouldn’t be offset by bad weather.

The clock can trigger alarms at a certain time or relative to time of dawn or dusk. The alarms are triggered according to last synchronized state, so bad weather shouldn’t affect them. Because the clock knows when it’s not synchronized, we can choose when to make decisions based on criteria other than time.

The clock’s time will be close to apparent solar time. Most of the time it won’t match standard time.

The clock is useful for controlling events in your garden without ever having to set time manually, via NTP or via GPS.

Read More