What you will find here is intersections of art, design, and technologies of movement, light, sound, sensing, and control.

making blog

test

Submitted by Ed_B on Sun, 12/20/2009 - 19:08

test this

here

Motorized Pan & Tilt System by Philomène Longpré

Submitted by ayu on Sat, 12/19/2009 - 23:32

Philomène Longpré was a graduate student at the Art and Technolgy Dept, she is now studying her Ph.D at DXARTS in Digital Arts and Experimental Media.  She was asked to design and fabricate a motorized pan tilt system for mounting any camcorders, small video projectors, sensors, or sculptural parts. She sent me this link  of her tutorial to share with us. You can learn more by clicking on her tutorial link below. Here are pics from her tutorial.

http://wiki.dxarts.washington.edu/groups/tutorialsdemos/wiki/10404/Design_and_Fabrication_Tutorial.html

Philomène Longpré's webite www.philox.net/

PCF8575 I2C port expander

Submitted by Ed_B on Tue, 12/15/2009 - 18:29

A port expander gives you more i/o from an MCU by using a small amount of i/o in clever ways. A typical application is to run 128 LED's from an Arduino. 

One of our faculty was suffering at the hands of a port expander board sold by SparkFun. I hope this posting helps.

This device uses a Two Wire Interface called I2C. I2C is hard to understand if you've never studied i/o buses, so what we need is a good example. The SparkFun board is based on a Texas Instruments chip called a PCF8575. It has 16 lines that are divided into two bytes. You can read from or write to each byte individually.

These pins can only supply  a little current. Surprisingly, you turn on an LED on by switching the GROUND side of the LED. This is called sinking. To turn the LED  ON, you make the pin LOW. The chip can sink a lot. But it can only source 5mA, which will make for a very dim LED. Wire like this:

(V+)   --->  LED  --->  -\/\/\/\-   ---> chip pin

To set the address of the chip, you put tiny solder bridges on the back of the board. There are three address lines. Solder-bridging a line to a ground pad makes that address line zero. All three lines are solder-bridged to ground to give the unit in the Arduino example (below) an address of zero.

 

The ArtBus protocol is MUCH MUCH easier to deal with. Just sayin.

 

/* 

This program sends 16 bits of data to a PCF8575 I2C port expander   

Ed Bennett 12-15-09

 

Expander board pins: These have NOTHING TO DO with analog. They just use the pins.

INT -- not connected
SCL -- Arduino analog 5
SDA -- Arduino analog 4

*/

#include <Wire.h>

byte address = 0x20;   // address of PCF8575 number zero
                     
void setup()
{
   Wire.begin();       // join i2c bus as master
}

// byte x counts up while byte y counts down

void loop(){
  unsigned char x;
  unsigned char y;
  
  for (x=0, y=255; (x+y)==255; x++, y--){

      Wire.beginTransmission(address);   // send the address and the write cmnd
      Wire.send(x);                      // pack the first byte
      Wire.send(y);                      // pack the second byte
      Wire.endTransmission();            // send the data

      delay(50);    
   }


     

 

ArtBus H-Bridge driver schematic

Submitted by Ed_B on Wed, 12/09/2009 - 14:49

Here is the schematic for the AVR atmega168 based ArtBus board. The firmware is almost at beta. More on that soon.

ArtBus boards back from the factory

Submitted by Ed_B on Sun, 12/06/2009 - 16:24

Well, here it is. I'm embaressed to say that the design worked the first time. That never happens! But it is a relief.

 

If there's any single trick to getting a board so that all the parts fit, it's the paper model trick. Here's the almost last revision before going to press.

 I'm way behind in posting, so I'll make this the last post on the CAD part of the process. The last steps pretty much follow the official KiCad tutorial on their website, but I'll summarize it in a few words.

After the board is done in PCBNEW, you post it out to files that go to the board house. In KiCad, the menu item that gets you there is "plot". The plot function makes one CNC file for each layer or process that goes between a blank PCB board and the finished board. In the plot function there are a bunch of layers you can turn on or off. The layers used in this board are

  • bottom solder mask
  • bottom (back side) copper
  • top (component side) copper
  • top solder mask
  • top legend (printed text)

 Additionally there are two other "technical layers" that produce CNC files. One is the border layer, which is jut a rectangle delimiting the board edges. The other is a registration mark layer that shows which end is up.

All these layers are in the Gerber g-code format which is used to run photoplotters. Photoplotter machines actually make the silkscreen image that is used in processing each layer of the board. There is one other CNC file you output in the plotting stage, but it isn't a plot file. The board house's CNC drilling machine takes "drill files". A common drill file format is Excellon RS274X.

As a last step before shipping the files to the board house, it is very good practice to run the plot files through a g-code viewer.  All kinds of nasty surprises can be caught at this stage. A g-code viewer isn't necessarily part of the CAD suite, and I think it's better if it isn't. The viewer plots the different layers of the board as the inverse of the process used in drawing them to begin with. It's kind of like using multiplication to check the result of hand dividing two numbers. If the two don't match, STOP. Find the source of the discrepency and fix it.

In the case of this board, I found out after it was all done that one of the part libraries had errors that didn't show up earlier in KiCad. The exact problem was that the solder mask layer on certain parts layer failed to provide holes to solder the parts onto the board. Very, very bad. I had to modify the componants in the library to fix the pads. It was a close call.

One thing needs to be clear. Board houses are in the business of running CNC files on production machines. They don't care what's in the files, and it's not their problem if you don't like your result. It's your responsibility to get it right before you upload your files, enter your credit card number into ther website, and hit send.

It's really best to spend the extra time and expense doing a short run of maybe five boards to see where the bugs are in your design before committing to a larger quantity order.

Modular synthesizer, smells great but no sound.

Submitted by zipTieIII on Wed, 11/25/2009 - 02:39

I'm building this modular synthesizer as a commision for a guy in Connecticut. I'ts housed in an old hardback suitcase with a wooden control panel, the legend of which is "printed" using the laser cutter and some crafty color filling.

The PCBs I'm using for the unit's three modules (16-step sequencer, VCF, VCO) are from Ray Wison's www.musicfromouterspace.com. I originally recieved this order back in 1/09 and had the thing mostly built by about mid February. When I first got the panel wiring all buttoned up and tried to turn it on, I got zero response from any module. Not surprising considering the sizeable parts list requires one to manually compile and order from electronics suppliers, which leaves a lot of room for error. I then proceeded to make a substantially ignorant judgement call and connected the -12V from my power supply to the system ground (since there are op-amps and other friends aboard the system uses 3-poles V+,V-,GND) just to "see". It worked! Not in a good way though. The counting logic and transport controls worked like a snap on the sequencer side, but no matter what each step's votage was tuned to, the CV would ouput a constant mirror of the system's supply voltage (15VDC). Not very useful for producing interesting synth compositions.     

Anyway, the VCF and VCO were apparently trashed as well. At this point with a  sugar in the gas tank situation on my hands, I back-burnered the project and let the client's faith in me slowly dwindle over a period of several months, through which I periodically tested individual components, re-flowed joints, purchased new ICs, sent out dissapointing updates etc... I eventually concluded that buying an entirely new round of components (boards and all) was the only sure way to eliminate all variables. I did this about a month ago, and after completely re-assembling everything, I was left with the same result. Silence, and no led indication of working logic. My hair grew back slowly over the following weeks, and I decided to consult Mr. Bennet in hopes that I could salvage my relationship with a now skeptical client. I have attached a few shots of the unit all put together below, enjoy the view! If I can do nothing else right, I think I make an ok housing!

Anticlimacticaly,

Kyle

ArtBus board with Arduino code

Submitted by Ed_B on Tue, 11/24/2009 - 19:36

This is pre-alpha code for the four-channel H-bridge controller which is the subject of the earlier postings on Kicad. When it gets more to late alpha (hopefully in the next day or two) it'll look rather different. It's mostly slash and burn from the PIC MCU version of the first ArtBus board, with just enough Arduino/avr-gcc to make it compile for testing.

The html formatting of the code below is done by using the html export function in the Kate editor, then opening the html file in a firefox tab, then copy and paste to here.


// AB_AVR_PWM_03.cpp
// Ed Bennett 10-21-09

/*

This is a .cpp file which compiles against the arduino libraries without the
.pde extension. The makefile is hacked from the arduino playground makefile for
use with your own code editor. The makefile builds and burns the program with
the avrispmkii by typing "make".

The makefile can also burn the fuses by typing "make fuses". Do this on a new
chip.

The .cpp program file is like a normal MCU C program except that init() must be
called to start up the wiring code.

(1) make an empty folder with the same name as your .cpp file will have, like
"my_mcu_prog_v1"

(2) copy the makefile into the folder and change it so that TARGET =
my_mcu_prog_v1    SAVE THE FILE

(3) in the new folder, create, copy, or open your .cpp program file like
"my_mcu_prog_v1.cpp" in an editor
like textedit or Smultron

(4) open a terminal window in the my_mcu_prog_v1 folder

(5) edit your code

(6) type make in the terminal to build 'n burn

(7) goto (5)

Note: avrdude coughs up an error at the end of the burn:
"Verify error - unable to read lfuse properly. Programmer may not be reliable."
The error seems harmless. Its origin is unknown.

*/
/*
ATMEGA168 DIP-28 PIN MAPPINGS TO ARDUINO DIECIMIELIA & AB H-BRIDGE CONTROLLER

DIP-28  AVR     Func    Ardu        AB              Mask

1       C6      RST     RST         RST
2       D0      RXD     D0/RX       AB_TO_MCU    
3       D1      TXD     D1/TX       MCU_TO_AB
4       D2      D2      D2          D4              PD 1<<2
5       D3      D3      D3/PWM      PWM1/D5         PD 1<<3  
6       D4      D4      D4          --
7       V+      --      --          --
8       DGND    --      --          --
9       XTAL    --      --          --
10      XTAL    --      --          --
11      D5      OC0B    D5/PWM      D1              PD 1<<5    
12      D6      OC0A    D6/PWM      --
13      D7      D7      D7          D3              PD 1<<7
14      B0      B0      D8          D2              PB 1<<0
15      B1      OC1A    D9/PWM      PWM2/D6         PB 1<<1
16      B2      OC1B    D10/PWM     PWM3/D7         PB 1<<2        
17      B3      OC2A    D11/PWM     PWM4/D8         PB 1<<3
18      B4      B4      D12         --
19      B5      B5      D13         --
20      AVCC    --      --          --
21      AREF    --      --          --
22      GND     --      --          --
23      C0      ADC0    A0          --
24      C1      ADC1    A1          ADDR_VALID LED  PC 1<<1
25      C2      ADC2    A2          --  
26      C3      ADC3    A3          SETUP SWITCH    PC 1<<3
27      C4      ADC4    A4          ERROR LED       PC 1<<4
28      C5      ADC5    A5          RS585 TX=H,RX=L PC 1<<5

*/

#include "WProgram.h"
#include <avr/io.h>
#include <avr/wdt.h>
#include <ctype.h>

// from a post by Eric Weddington on avrfreaks.net
// p is a byte variable, m is the bit position in a mask
/*
#define DIO_1 PORTD,5
#define DIO_2 PORTB,0
#define DIO_3 PORTD,7
#define DIO_4 PORTD,2
#define DIO_5 PORTD,3
#define DIO_6 PORTB,1
#define DIO_7 PORTB,2
#define DIO_8 PORTB,3
*/

// i/o bit Mask for AB ports B and D
#define DM1 0x20
#define DM2 0x01
#define DM3 0x80
#define DM4 0x04
#define DM5 0x08
#define DM6 0x02
#define DM7 0x04
#define DM8 0x08


// port associated with a pin
#define DP1 PORTD
#define DP2 PORTB
#define DP3 PORTD
#define DP4 PORTD
#define DP5 PORTD
#define DP6 PORTB
#define DP7 PORTB
#define DP8 PORTB



// DDR asscoicated with a pin
#define DR1 DDRD
#define DR2 DDRB
#define DR3 DDRD
#define DR4 DDRD
#define DR5 DDRD
#define DR6 DDRB
#define DR7 DDRB
#define DR8 DDRB
/*
# define PORTD_MASK (0x1D) // portd pins we use
# define PORTB_MASK (0xE2)

# define PORTD_MASK (0xB8) // portd pins we use
# define PORTB_MASK (0x47)
*/
# define PORTD_MASK (0xAC) // portd pins we use
# define PORTB_MASK (0x0F)


#define ADDR_LED        1  // my address is valid LED - pin C1
#define ERROR_LED       4  // there was an error LED  - pin C4
#define RXTX_SWITCH     5  // line controls data direction on the
                           // RS-485 transciever chip - pin C5 XMIT=H, RCV=L

// errors - values add. A get OVERFLOW, 1 and a UNDERFLOW, 2
// together would cause error_last to have the value 3
#define OVERFLOW    0b00000001      // get overflow flag     (1)
#define UNDERFLOW   0b00000010      // get underflow flag    (2)
#define TIMEOUT_FLG 0b00000100      // ser in timeout flag   (4)
#define BAD_CMD     0b00001000      // invalid command       (8)
#define BAD_VAL     0b00010000      // bad param value       (16)

#define FAST_COM    1   // 115200 baud
#define SLOW_COM    0   // 19200 baud
                                
                                
// top level states
#define WAITING     0
#define CHK_ADDR    1
#define RECV_CMD    2
#define RECV_PARM   3
#define RUNNING_CMD 4
#define PAUSED      5

#define SPACE 0x20

#define BEGIN_XMIT PORTC |= 1 << RXTX_SWITCH; delayMicroseconds(200);  // 100uS
// minimum -- doubled for safety
#define END_XMIT PORTC &= ~(1 << RXTX_SWITCH);

void reboot(void);
int MyBug_1_pwm(void);
int clearPin(int pin);
int setPin(int pin);
int getInt(int *converted);

char myAddr = 'A'; // default values
char myGroup = 'Z';

byte state;

byte errByte;

byte ledPin = 8;      // LED connected to digital pin 14
//int pwmPin = 9;


// Promiscous listen to bus during idle. Wait for "Attention" character (!).
byte waitForAttention(void){  
    while(Serial.read() != '!');
    return 1;
}

int clearPin(int pin){

    switch(pin){
        case 1:
            DDRD |= (1 << 5);
            PORTD &= ~(1 << 5);
            break;
        case 2:
            DDRB |= (1 << 0);
            PORTB &= ~(1 << 0);
            break;
        case 3:
            DDRD |= (1 << 7 );
            PORTD &= ~(1 << 7);
            break;
        case 4:
            DDRD |= (1 << 2);
            PORTD &= ~(1 << 2);
            break;
        case 5:
            DDRD |= (1 << 3);
            PORTD &= ~(1 << 3);
            break;
        case 6:
            DDRB |= (1 << 1);
            PORTB &= ~(1 << 1);
            break;
        case 7:
            DDRB |= (1 << 2);
            PORTB &= ~(1 << 2);
            break;
        case 8:
            DDRB |= (1 << 3);
            PORTB &= ~(1 << 3);
            break;
        default:
            errByte |= BAD_VAL;
            BEGIN_XMIT
            Serial.print("bad pin");
            END_XMIT
            return 0; //fail
        break;
    }
    return 1; //succeed
}


int setPin(int pin){

    switch(pin){
        case 1:
            DDRD |= (1 << 5);
            PORTD |= (1 << 5);
            break;
        case 2:
            DDRB |= (1 << 0);
            PORTB |= (1 << 0);
            break;
        case 3:
            DDRD |= (1 << 7);
            PORTD |= (1 << 7);
            break;
        case 4:
            DDRD |= (1 << 2);
            PORTD |= (1 << 2);
            break;
        case 5:
            DDRD |= (1 << 3);
            PORTD |= (1 << 3);
            break;
        case 6:
            DDRB |= (1 << 1);
            PORTB |= (1 << 1);
            break;
        case 7:
            DDRB |= (1 << 2);
            PORTB |= (1 << 2);
            break;
        case 8:
            DDRB |= (1 << 3);
            PORTB |= (1 << 3);
            break;
        default:
            errByte |= BAD_VAL;
            BEGIN_XMIT
            Serial.print("bad pin");
            END_XMIT
            return 0; //fail                
        break;            
            
    }
    return 1; //succeed  
}



int putByte(int outByte){
    int mask = 1;
    
    DDRD = PORTD_MASK; // set all to output
    DDRB = PORTB_MASK;
        
    if(mask & outByte){     // pin 1
        PORTD |= (1 << 5);
    } else {
        PORTD &= ~(1 << 5);
    }

    mask <<= 1;
            
    if(mask & outByte){     // pin 2
        PORTB |= (1 << 0);
    } else {
        PORTB &= ~(1 << 0);
    }
    
    mask <<= 1;

    if(mask & outByte){     // pin 3
        PORTD |= (1 << 7);
    } else {
        PORTD &= ~(1 << 7);
    }
    
    mask <<= 1;

    if(mask & outByte){     // pin 4
        PORTD |= (1 << 2);
    } else {
        PORTD &= ~(1 << 2);
    }

    mask <<= 1;
    
    if(mask & outByte){     // pin 5
        PORTD |= (1 << 3);
    } else {
        PORTD &= ~(1 << 3);
    }

    mask <<= 1;
    
    if(mask & outByte){     // pin 6
        PORTB |= (1 << 1);
    } else {
        PORTB &= ~(1 << 1);
    }
    
    mask <<= 1;
    
    if(mask & outByte){     // pin 7
        PORTB |= (1 << 2);
    } else {
        PORTB &= ~(1 << 2);
    }

    mask <<= 1;
                DDRB |= (1 << 3);
     if(mask & outByte){     // pin 8
        PORTB |= (1 << 3);
    } else {
        PORTB &= ~(DM8);
    }  
    
    return 1; //succeed  
}







int readPin(int pin){
    byte read_val = 0;
        
    switch(pin){
        case 1:
            DDRD &= ~(1 << 5); // set pin to input
            read_val = PORTD & (1 << 5);
        break;
        case 2:
            DDRB &= ~(1 << 0);
            read_val = PORTB & (1 << 0);
        break;
        case 3:
            DDRD &= ~(1 << 7);
            read_val = PORTD & (1 << 7);
        break;
        case 4:
            DDRD &= ~(1 << 2);
            read_val = PORTD & (1 << 2);
        break;
        case 5:
            DDRD &= ~(1 << 3);
            read_val = PORTD & (1 << 3);
        break;
        case 6:
            DDRB &= ~(1 << 1);
            read_val = PORTB & (1 << 1);
        break;
        case 7:
            DDRB &= ~(1 << 2);
            read_val = PORTB & (1 << 2);
        break;
        case 8:
            DDRB &= ~(1 << 3);
            read_val = PORTB & (1 << 3);
        break;
            
        default:
                errByte |= BAD_VAL;
                BEGIN_XMIT
                Serial.print("bad pin");
                END_XMIT
                return 0; //fail                
        break;
    }
    
    return read_val; // succeed
}

      
    
/*
        switch(which_line){
            case 1:
                read_val = input(IN_OUT_1);
                break;
            case 2:
                read_val = input(IN_OUT_2);
                break;
            case 3:
                read_val = input(IN_OUT_3);
                break;
            case 4:
                read_val = input(IN_OUT_4);
                break;
            case 5:
                read_val = input(IN_OUT_5);
                break;
            case 6:
                read_val = input(IN_OUT_6);
                break;
            case 7:
                read_val = input(IN_OUT_7);
                break;
            case 8:
                read_val = input(IN_OUT_8);
                break;
        }       // let bogus values fall through without comment
        start_print();
        printf("%u\n",read_val);
        end_print();
        return 1;
    }else{
        return 0;
    }
    
}
*/

int process_cmd(int cmd){
        int which_line = 0;
        int portVal;
            
        switch(cmd){
            /*
            case 'a':
                getInt(&which_line);  // which line to write?
                readPin(which_line);
            break;

            case 'b':
                MyBug_read_byte();
            break;

            case 'i':
                MyBug_toggle_pin();
            break;
*/
            case 'j':    
                getInt(&which_line);  // which line to write?
                clearPin(which_line);
            break;

            case 'k':
                getInt(&which_line);  // which line to write?
                setPin(which_line);
            break;

            case 'n':
                getInt(&portVal);
                putByte(portVal);
            break;

  


            case 'p':
  
                MyBug_1_pwm();  
                return WAITING;      
            break;    
    
            case 'q':
                //x
        
            break;    
    
            case 'g':
                //x
        
            break;    
    
            case 'h':
                return PAUSED;
        
            break;    
    
            case 'w':
                //x
        
            break;    
    
            case 'x':
                BEGIN_XMIT
                Serial.println("foo");
                END_XMIT
            break;    
    
            case 'y':
                //x
            break;    
    
            case 'z':  
                reboot();
    
            case ';':
            // sometimes these slip through
            break;
  
    
            default:
                errByte &= BAD_CMD;
  
                BEGIN_XMIT
                Serial.print("bad cmd in switch");
                Serial.println(cmd);  
                END_XMIT

            break;      

    
    }
}


/*
 This is an Atmel hack for rebooting.
 It also requires this to be at the very top of main():    
         MCUSR = 0;
         wdt_disable();        
*/
void reboot(void){

        WDTCSR = _BV(WDE);
        wdt_reset();
        wdt_enable(WDTO_30MS);        
        while (1); // DIE!  
}



int MyBug_1_pwm(){

    int pwmChan;
    int pwmVal;
    int AB_chan;
  
    if(!(getInt(&AB_chan))){
/*
        BEGIN_XMIT
        Serial.println("Bad get pwmChan MyBug");
        END_XMIT
*/
        return 0;
    }
  
  // convert ArtBus PWM pin names to arduino pin names
    switch (AB_chan){
        case 1:
            pwmChan = 3; // AVR pin # 5        
            break;
        case 2:
            pwmChan = 9; // AVR pin # 15        
            break;
        case 3:
            pwmChan = 10; // AVR pin # 16        
            break;
        case 4:
            pwmChan = 11; // AVR pin # 17      
            break;
        default:
            //error = badparm;
/*
        BEGIN_XMIT
        Serial.print("unknown chan ");
        Serial.println(AB_chan);  
        END_XMIT    
*/
              
        break;
    }

    if(!(getInt(&pwmVal))){
/*
        BEGIN_XMIT        
        Serial.println("Bad get pwmVal 2 @ MyBug");
        END_XMIT
*/        
        return 0;
    }
    pinMode(pwmChan, OUTPUT);
    analogWrite(pwmChan, pwmVal);
}

        
// when we are expecting data, a timeout means an error
byte getExpectedData(){
    char val;
    long time;
    long timeout;  
    
    timeout=time=millis(); // start counting milliseconds

// try getting serial data for 1 to 2 milliseconds (it will vary)
    while(time - timeout < 2){
            if(Serial.available()){
            val = Serial.read();
            return val;
         }
         time=millis();
    }    
    
/*
    BEGIN_XMIT
    Serial.println("serial timeout @ getExpected");
    END_XMIT
*/
    
    return 0;  // while loop expired before data arrived (error)
}


int getChar(char *ascVal) { // returns success
    char asciival;     // scratchpad variable
    asciival = getExpectedData();
        
    if (isascii(asciival)){       // null would be bogus here
        *ascVal = asciival;
/*        
        BEGIN_XMIT
        Serial.print("asciival @ getChar ");
        Serial.println(asciival);
        END_XMIT
 */      
        return 1;
    }
/*
    BEGIN_XMIT
    Serial.println("no char @ getChar");
    END_XMIT
*/
    return 0;   // failed from timeout
    
}


int getInt(int *converted) { // returns success
    char asciival;
    char stringarray[6];
    int i = 0;
    int tries = 0;

        
    // fill the character array for conversion to an int
    do {
        asciival = getExpectedData();
        if (asciival){  // null would be bogus here
            if ((asciival == '\n') || (asciival == '\r')) continue;
            stringarray[i] = asciival;
            i++;
        }else{
/*            
            BEGIN_XMIT
            Serial.println("do-while @ getInt()");
            END_XMIT
*/
            return 0;   // failed from bad char
        }      

    }while((isdigit(asciival)) && (i<=5)); // 5-char string + \0 -- do-while

/*
    BEGIN_XMIT
    Serial.print("asciival @414 ..");
    Serial.print(asciival);
    Serial.println("..");
    END_XMIT
*/

    if (asciival == ';' || asciival == ' ') { // delimiter is last member of
array        

        // add end of array marker for stringiness
        stringarray[i] = 0; //overwrite delimiter with null to make string
        *converted = atoi(stringarray);  //didn't check for legit ascii
    return 1;


    }else{
/*
        BEGIN_XMIT
        Serial.println("bad convert @ getInt()");
        END_XMIT    
*/    
        return 0;
    }
}


void blinkADDR_LED() {
    PORTC |= 1 << ADDR_LED;
    delay(250);
    PORTC &= ~(1 << ADDR_LED);
    delay(250);
}

void greet(void){
    char n;
    n = (myAddr - 'A') * 3; // ~30 millis per letter of the alphabet
    delay(n*10);        // so each unit prints at a different time    
    
    blinkADDR_LED();
    blinkADDR_LED();
    blinkADDR_LED();
    
    BEGIN_XMIT
    Serial.print("\n\rHi from ");
    Serial.print(myAddr);
    Serial.println("! I'm an ArtBus H-Bridge controller. (rev 0.091020) \n\r");
    END_XMIT
}



//
-----------------------------------------------------------------------------
        
int main(void){

         char val;
        
/*
    After a software reset, "!Az;" the watchdog timer remains running and must
    be disabled to keep out of an endless reset loop. The MCU Status Register
is
    cleared first (it likes it that way) so that the watchdog timer can then be

    disabled. The WDT is only used here as a way to reboot the chip.
*/    
         MCUSR = 0;
         wdt_disable();
        
        init();
        
         Serial.begin(115200);        

        DDRC = 0xF7; // port c all out except setup switch

        greet();
        
        state = WAITING;
        

        
        
        while(1){

            switch(state){
                case WAITING:
                    waitForAttention();  // ENTIRE PROGRAM BLOCKS HERE
                    val = getExpectedData();
                    if(val){
                        state = CHK_ADDR;
                    }else{
                        state = WAITING;
                    }
            break;
                                
            case CHK_ADDR:
                if(myAddr == val){
                    state = RUNNING_CMD;
                    PORTC |= 1 << ADDR_LED; // hi.
                }else{
                    state = WAITING;
                    PORTC &= ~(1<<aDDR_LED);
                }
            break;

            case RUNNING_CMD:
                    if(getChar(&val)){
                    state = process_cmd(val); // returns WAITING
                    }else{
                  state = WAITING;
                    }                      
            
            break;

            default:
                state = WAITING;
            }
    
        }
}

        


morse code

Submitted by jsebur on Thu, 11/19/2009 - 21:54

i am trying to write a code that will type out individual letters in morse code at random, i have a morse code code for the arduino, which works through the serial port.  i.e, i type HELLO WORLD, it spells that out in morse code through pin 13.  this works great, but i would like to retro fit that code, so instead using the serial port, the program just generates letters.  I would like it to randomly choose a letter, and randomly choose a pin to print that letter(in morsecode).  here is my current program:

Using OpenCV face tracking to move motors

Submitted by Alex_Simes on Wed, 11/18/2009 - 14:09

Ed asked me to post the steps for making this project for future people to reference.

 I am building a project that is a mask placed near a wall at roughly eye level. The mask needs to be able to identify people and look at them when they look at it.

need processing coding help! collaboration???

Submitted by jkim58 on Wed, 11/18/2009 - 12:40

I'm jongock Kim, and 2nd year grad student in Fiber Department. I am working on my final project for E-textiles and the coding is a bit complicated to tackle on my own. For my project, I would like to make an interactive weaving where the user can draw graffitti on my woven wall imagery. It is going to be hand woven fabric, with a photographic wall image in gray scale. At the moment I have this system working with a little green laser pointer: http://muonics.net/blog/index.php?postid=26

Syndicate content