Tuesday, March 24, 2009

Thoughts on GPL, the Open Company concept, and making $ therein

One aspect of the philosophy of GPL is to contribute back to the community. However, as we all know in the GPL license the only way to contribute is by submitting code.

This creates several problems; the primary being a chasm between it and all other economic activity. This has resulted in lots of people coming up with very creative but ultimately ancillary ways to fund GPL activity, the primary being support. There is probably a mountain of literature written about this and so I won't go into them more deeply here other than to summarize:

These methods are not satisfactory because the effort/reward relationship is obscure at best and at worst rewards the wrong activities.

So let us modify the GPL with a economic clause. This would essentially state, "If you want to use this software without licensing your derivative software via GPL, then simply pay us money.

In this way a company or individual can contribute back to the project in the traditional ($) manner (as an aside, does it also allow code contributions to be valued monetarily and therefore taxed?). But of course what should the project do with that cash? While many projects could definitely use the money to pay for server space and bandwidth; we can imagine an extremely successful piece of OSS that is actually generating a surplus of money. It would obviously be inappropriate for the project founder to keep it since in theory the software has benefited from submissions from many individuals.

That observation cannot sit in anyone's mind without producing the obvious answer within a modern meritocracy:

Project surplus should be distributed to individuals according to level of contribution

If the project is successful, one might imagine that this could become key contributors primary source of income. Essentially they would be "employees" of the project's "company", but without some of the pain associated with corporate involvement (and perhaps also without some of the benefits).

Of course, this brushes all kinds of issues under the rug such as how to measure "level of contribution". Let me throw out an initial breakdown formula:

contribution = "Trust Network" opinion * (alpha * sum(cool feature values) + beta * lines of code + delta * sum(bug fix value) - epsilon*(sum bugs you created))

"Trust Network opinion" = how other people rate you; used to catch people who are padding out their contributions by writing wordy code, etc.

Alpha, beta, and delta = arbitrary weighting factors depending on what's most important.

"cool feature values" = How much people like the feature you added (or maybe real-time feedback reporting what features the users are using)

"lines of code" should be obvious

"bug fixes" = Fixing bugs is a boring nasty job but someone has to do it.

And of course your contribution should be penalized by the # of bugs found; after all, if someone has to essentially rewrite your stuff; I'm not sure if you deserve too much credit.

But this only focuses on the code. How about the community? We can imagine similar metrics created for support forums; # of posts, response time, quality of posts, etc, and combined into a monster "value" equation. And documentation...

Even the necessary evil of "hierarchy and planning" can perhaps be captured by a pyramid scheme whereby section owners "contribution value" includes a tiny % of all contribution values to that section.

All of this begs the question: "Is it possible to capture all business activities?" To create an "Open Company?"

All of the above are my own ideas except for the word "Open Company". I was inspired to blog about them today because I think we are about to take the initial steps in regard to feasibility; there is a company out there who is going to try to do just that.

You can read a bit about it at: http://e-texteditor.com/blog/2009/opencompany

Wednesday, March 11, 2009

Arduino L298 stepper motor driver

Here is an example Arduino sketch to drive a stepper motor using the L298 chip. The actual driver is the "StepperL298N" class, and then there is some code to test it. When you instantiate the class, pass in the 4 Arduino pins that you have connected to the stepper motor. For example, "StepperL298N motor(4,5,6,7)" will drive a motor connected to Arduino pins 4,5,6,7. If you need to drive 2 motors, just create 2 instances of the class with different pins!

To move the motor 1 tick, call the step(bool direction) member function. Call it with 1 to go forward, and 0 to go backwards. The faster you call it, the faster the motor will go. Note that the Arduino can easily call step() much faster than the motor can possibly be driven, so you must insert a delay by calling the delay function. For my test motor (and old AMP 2.3 volt 60oz*in, which I got from taking apart a printer) you have to delay at least 5ms for the motor to work.



/*
* stepperL298N
* Copyright 2008 G. Andrew Stone
* Licensed under the Common Public License V1.0
* For the full text of this license see: http://www.opensource.org/licenses/cpl1.0.php
*
*/

int ledPin = 13;

void setup() // run once, when the sketch starts
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}

void mydelay(int clk)
{
int i;
for (i=0;i< clk;i++);
//delay(clk);
}

class StepperL298N
{
public:
byte pins[4];
byte curState;
byte* lut;
StepperL298N(byte pin1,byte pin2,byte pin3,byte pin4);

void step(boolean dir);
void halfStep(boolean yes) { if (yes) lut = halfStepLut; else lut = fullStepLut;}
void start() { curState = 0xa;}
void free() { curState = 0; }
void brake() { curState = 0; }

byte fullStepLut[16];
byte halfStepLut[16];
};


StepperL298N::StepperL298N(byte pin1,byte pin2,byte pin3,byte pin4)
{
pins[0] = pin1; pins[1] = pin2; pins[2]=pin3; pins[3] = pin4;
lut = fullStepLut;
for (int i=0;i<4;i++)
{
pinMode(pins[i], OUTPUT); // sets the digital pin as output
}

memset(&fullStepLut,sizeof(byte)*16,0);
memset(&halfStepLut,sizeof(byte)*16,0);

// High nibble goes one way, low the other
fullStepLut[0] = 0;
// 1010 -> 1001 -> 0101 -> 0110
fullStepLut[0xa] = 0x9 | 0x60;
fullStepLut[0x9] = 0x5 | 0xa0;
fullStepLut[0x5] = 0x6 | 0x90;
fullStepLut[0x6] = 0xa | 0x50;

halfStepLut[0] = 0;
// 1010 -> 1000 -> 1001 -> 0001 -> 0101 -> 0100 -> 0110 -> 0010
halfStepLut[0xa] = 0x8 | 0x20;
halfStepLut[0x8] = 0x9 | 0xa0;
halfStepLut[0x9] = 0x1 | 0x80;
halfStepLut[0x1] = 0x5 | 0x90;
halfStepLut[0x5] = 0x4 | 0x10;
halfStepLut[0x4] = 0x6 | 0x50;
halfStepLut[0x6] = 0x2 | 0x40;
halfStepLut[0x2] = 0xa | 0x60;
}

void StepperL298N::step(boolean dir)
{
curState = lut[curState];
if (dir) curState &= 0xf;
else curState >>= 4;
for (int i=1,j=0;i< 16;i*= 2,j++)
{
byte lvl = LOW;
if (i&curState) lvl=HIGH;
digitalWrite(pins[j],lvl);
}
}


int serDataVal = LOW;
void loop() // run over and over again
{
unsigned long int j;

StepperL298N motor(3,4,5,6);
motor.halfStep(true);
motor.start();

for (j=0;j< 1000;j++)
{
motor.step(1);
digitalWrite(ledPin, j&1); // sets the LED on
delay(5+j/10); // Change the delay to change the rate the motor spins
}
motor.halfStep(false);
motor.start();
for (j=0;j< 1000;j++)
{
motor.step(0);
digitalWrite(ledPin, j&1); // sets the LED on
delay(5+j/10);
}
}

Michael Margolis ('mem' on the Arduino.cc forum) was kind enough to let me cross-post a schematic: