Go Down

Topic: LEDS and 74HC595 shift register (Read 10 times) previous topic - next topic

John_Ryan

#15
Aug 16, 2007, 11:52 am Last Edit: Aug 16, 2007, 11:54 am by John_Ryan Reason: 1
Here's a sample php script that toggles the value of LED7 in the left (1st) group of 8 LED's

Code: [Select]

<?php

// php demo script - toggle LED 7 on and off via www

// runs on yourwww.com - save it as toggle.php

// All LEDs on = FF FF
// LED 7 off = FF BF
// LED 7 on = FF FF

// Read the current values

$file fopen("settings.txt","r"); // open settings.txt
$settings=fread($file,filesize("settings.txt")); // read whole file

// split pairs into strings
$myhex1 substr($settings02);
$myhex3 substr($settings32);

// show user what the present values are
echo $myhex1;
echo 
"<br />";
echo 
$myhex3;
echo 
"<br />";

fclose($file);

// toggle LED 7


// if LED 7 is on - turn it off
if ($myhex3=="FF") {
      
$newhex3="BF";
}

// if LED 7 is off - turn it on
if ($myhex3=="BF") {
      
$newhex3="FF";
}

$towrite=$myhex1// restore right settings 
$towrite .=chr(9); // add in tab delimiter used by processing
$towrite .=$newhex3// store new value for left settings - LED 7

// show the user what the new values are
echo "<br />";
echo 
$towrite;

// write values to settings.txt
$file fopen("settings.txt","w");
fwrite($file,"$towrite\n");
$file fclose($file);

?>



To toggle the LED status, press the refresh button on the browser. Response time's really good, about 1 second - so I could be sitting in France turning a LED on and off in the US via www.myserver.com/toggle.php

I know there's ways of doing this using other hardware and software. But I haven't seen anything Arduino like that I could recreate, plus, I like being able to add an indefinite number of 595's so the number of LED's, or relay's, one can control, is unlimited.

595's are cheap too - 4 bucks for 10 off eBay if you don't mind the dodgy sellers and their "floor sweeps".

John_Ryan

If you want to have all LEDs off, and only toggle LED 7 on and off, change the hex values from

// All LEDs on = FF FF
// LED 7 off = FF BF
// LED 7 on = FF FF

to

// All LEDs off = 00 00
// LED 7 on = 00 40
// LED 7 off = 00 00

It's actually LED 2, not 7, depending from which direction you look at the LEDs on the board.

I've got all the LEDs fired up to determine how long they'll last, but others may just want turn individual LEDs on and off, while leaving the rest off.

Here's an online binary to hex converter script I stumbled across, it's handy for visualizing if your not a binary to hex guru.

http://www.mathsisfun.com/binary-decimal-hexadecimal-converter.html


John_Ryan

#17
Aug 18, 2007, 12:28 pm Last Edit: Aug 18, 2007, 12:30 pm by John_Ryan Reason: 1
Now I want to add the 4021's - can anyone see a problem with this layout ?



I want the board to multiplex inputs and outputs at the same time, and use a hacked version of the code from both examples, but, before I go destroying the board I thought I'd check with you guru's first :)

John_Ryan

#18
Aug 20, 2007, 12:27 pm Last Edit: Aug 21, 2007, 02:14 am by John_Ryan Reason: 1
I'd been sifting through some of Tom's code and came across a processing/php solution to sending values from Arduino, via processing, to php, and then php writing the values to a .txt file on a web server.

This is significant for me, because I have a means of sending values from a .txt file stored on a web server to Arduino via processing, and now I have a way of Arduino talking back to the server via processing via php.

For example, I might like to have a digital input for each LED, so if a switch is turned on or off, the server side script can decide if it's going to turn a LED on or off.

code for processing

Code: [Select]

/* http client
original code by Tom Igoe
Starts a network client that connects to a server on port 80,
sends an HTTP 1.1 GET request.
Sends an input value to php
php writes the value to a text file on a web server
 */
import processing.net.*;
Client client;
int inputValue = 33;                    // number representing the input switch - this would be determined by the value Arduino sends to processing

void setup()
{
 // open a TCP socket to the host:
 client = new Client(this, "yourserver.com", 80);
 // send the HTTP GET request:
 client.write("GET /~youraccount/switch.php?receivedValue=" + inputValue + " HTTP/1.1\n");
 client.write("HOST: yourserver.com\n\n");
  println("\n\nSend complete\n");
}



php - switch.php

Code: [Select]

<?php
$filename 
'switched.txt';
// create string from the POST
  
$dataString $dataString.$_REQUEST['receivedValue'];
  
// add a linefeed and carriage return
  
$dataString $dataString."\r\n";

//  make sure the file exists and is writable first:
if (is_writable($filename)) {

   
// Open $filename in write mode
   
if (!$handle fopen($filename'w')) {
         echo 
"Can't open file $filename";
         exit;
   }

   
// Write $dataString to the opened file.
   
if (fwrite($handle$dataString) == FALSE) {
       echo 
"Can't write to file $filename";
       exit;
   }
  
// data successfully written:
   
echo "Wrote $dataString to file $filename";
   
// send a 0 to tell the remote side we're done:
  
echo "\0";
  
// close the file
   
fclose($handle);

} else {
   echo 
"The file $filename is not write-enabled.";
}
end;
?>




So, depending on what processing receives from Arduino, the value gets stored in the file switched.txt, located on the web server.

Once I've integrated the 4021's - I'll provide a more thorough explanation of how the Arduino sends and receives data from a web based php script, via processing.

I can think of a number of reasons why you would want web based communications like this, home security springs to mind, remote sensor monitoring via a web based interface, and being able to send data to Arduino over the internet.  

John_Ryan

So, the layout (above) with both 595 and 4021's works fine - nothing blew up, I'll post pic's when I get time.

The 595's still respond, so the LED switching works perfectly. And the serial window in Arduino echo's which input switch is on when a button is pushed.

In processing, I used port.read(); to collect the value of the switch sent by Arduino.

So now I'm writing a method to debounce the switch, once that's done - I'll incorporate the method of writing the input value from processing, to a .txt file on the server.

Then, I'll publish the php code for reading the values of switches, and changing which LED's are displayed, via a web based interface, without using Xport or any other device for handling web based communications with Arduino, just, USB Arduino and an internet connection, processing, php, 2 x .txt files, and a trusty Linux server :)




John_Ryan

Here's the Arduino code for both 595's and 7021's

I've currently got 3 x 595's and 1 x 7021 wired up, and all works well.

On the processing side it's a bit more of a headache. The methods for getting information from a .txt file stored on a web server are prone to falling over.

One of the methods falls over if there's a small interruption between my laptop and the router, which happens if 'something in the air' causes a temporary break in the connection. That method comes with a small note that there is "no error trapping", so I'm really bummed out about that.

The second method works better at handling breaks in the connection, but does a giant wobbly when there's a serialEvent anytime processing is sent the value of an input switch. The "Exception" error it throws is a hot little topic over at processing, and is the subject of a great deal of puzzlement, so I'm also bummed out about that. So I posed the question of how "in Beta" is processing, I also don't expect to get that answered.

I've posted over at processing, but I'm not confident of a solution anytime. Perhaps it's worth mentioning to people that processing has lots of bugs that aren't being fixed, and judging by their Alexa ranking, traffic at the site appears to be diminishing.

Code: [Select]


//  ::: Code for using 74HC595's for controlling arrays of LED's, and 7021's for reading arrays of switches

int latchPin = 8;  //Pin connected to ST_CP of 74HC595
int clockPin = 12; //Pin connected to SH_CP of 74HC595
int dataPin = 11; //Pin connected to DS of 74HC595

int inplatchPin = 10; //Pin connected to ST_CP of 7021
int inpdataPin = 9; //Pin connected to SH_CP of 7021
int inpclockPin = 7; //Pin connected to DS of 7021

int sentSwitch = 2;
//Define variables to hold the data
//for shift register.
//starting with a non-zero numbers can help
//troubleshoot
byte switchVar1 = 72;  //01001000
byte lowcBitNum = 7;
byte dBitNum = 6;
byte eBitNum = 5;
byte fBitNum = 4;
byte gBitNum = 3;
byte aBitNum = 2;
byte bBitNum = 1;
byte highcNum = 0;
boolean dBit;
long time = 0;
long debounce = 8000; // big long debounce

int firstByte;
int secondByte;
int thirdByte;
int val;
int serialInArray[4];
int serialCount = 0;

void setup() {
     //set pins to output because they are addressed in the main loop
     pinMode(latchPin, OUTPUT);
     //define pin modes
     pinMode(inplatchPin, OUTPUT);
     pinMode(inpclockPin, OUTPUT);
     pinMode(inpdataPin, INPUT);
     Serial.begin(9600);
}

void loop() {
     digitalWrite(inplatchPin,1);  //Pulse the latch pin / collect parallel data
     delayMicroseconds(20);
     digitalWrite(inplatchPin,0); //set it to 0 to transmit data serially

     //collect each shift register into a byte

     if (millis() - time > debounce) {

           switchVar1 = shiftIn(inpdataPin, inpclockPin);

           if (getBit(switchVar1, highcNum)) {
                 Serial.println("0");
                 time = millis();
           }
           if (getBit(switchVar1, bBitNum)) {
                 Serial.println("1");
                 time = millis();
           }
           if (getBit(switchVar1, aBitNum)) {
                 Serial.println("2");
                 time = millis();
           }
           if (getBit(switchVar1, gBitNum)) {
                 Serial.println("3");
                 time = millis();
           }
           if (getBit(switchVar1, fBitNum)) {
                 Serial.println("4");
                 time = millis();
           }
           if (getBit(switchVar1, eBitNum)) {
                 Serial.println("5");
                 time = millis();
           }
           if (getBit(switchVar1, dBitNum)) {
                 Serial.println("6");
                 time = millis();
           }
           if (getBit(switchVar1, lowcBitNum)) {
                 Serial.println("7");
                 time = millis();
           }
 
     }

 if (Serial.available() > 0) {
     serialInArray[serialCount] = Serial.read();
     serialCount++;
     if (serialCount > 3 ) {
           firstByte = serialInArray[1];
           secondByte = serialInArray[2];
           thirdByte = serialInArray[3];
           //ground latchPin and hold low during transmit
           digitalWrite(latchPin, 0);
           shiftOut(dataPin, clockPin, firstByte);
           shiftOut(dataPin, clockPin, secondByte);
           shiftOut(dataPin, clockPin, thirdByte);      
           //return the latch pin high to signal chip that it no longer needs to listen for information
           digitalWrite(latchPin, 1);
           serialCount = 0;
           sentSwitch = 2;
           }
     }
}

////// ----------------------------------------shiftOut function

void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
 int i=0;
 int pinState;
 pinMode(myClockPin, OUTPUT);
 pinMode(myDataPin, OUTPUT);
 digitalWrite(myDataPin, 0);
 digitalWrite(myClockPin, 0);
 for (i=7; i>=0; i--)  {
   digitalWrite(myClockPin, 0);
   if ( myDataOut & (1<<i) ) {
     pinState= 1;
   }
   else {
     pinState= 0;
   }
   digitalWrite(myDataPin, pinState);
   digitalWrite(myClockPin, 1);
   digitalWrite(myDataPin, 0);
 }
 digitalWrite(myClockPin, 0);
}


////// ----------------------------------------shiftIn function

byte shiftIn(int myinpDataPin, int myinpClockPin) {
 int inpi;
 int inptemp = 0;
 int inppinState;
 byte myinpDataIn = 0;
 pinMode(myinpClockPin, OUTPUT);
 pinMode(myinpDataPin, INPUT);

//Count Down
 for (inpi=7; inpi>=0; inpi--)
 {
   digitalWrite(myinpClockPin, 0);
   delayMicroseconds(0.2);
   inptemp = digitalRead(myinpDataPin);
   if (inptemp) {
     inppinState = 1;
     myinpDataIn = myinpDataIn | (1 << inpi);
   }
   else {
     inppinState = 0;
   }
   digitalWrite(myinpClockPin, 1);
 }
 return myinpDataIn;
}

////// ----------------------------------------getBit
boolean getBit(byte myVarIn, byte whatBit) {
 boolean bitState;
 bitState = myVarIn & (1 << whatBit);
 return bitState;
}

John_Ryan

My next attempt will be to wire up a parallax RFID board I've got, and integrate code from this example.

http://www.arduino.cc/playground/Learning/PRFID

The only problem I can see, is that it uses a 2400 baud serial connection, whereas, I'm already set up at 9600

Code: [Select]

// RFID reader for Arduino
// Wiring version by BARRAGAN <http://people.interaction-ivrea.it/h.barragan>
// Modified for Arudino by djmatic


int  val = 0;
char code[10];
int bytesread = 0;

void setup() {

Serial.begin(2400); // RFID reader SOUT pin connected to Serial RX pin at 2400bps
pinMode(2,OUTPUT);   // Set digital pin 2 as OUTPUT to connect it to the RFID /ENABLE pin
}

digitalWrite(2, LOW);                  // Activate the RFID reader


void loop() {

 if(Serial.available() > 0) {          // if data available from reader
   if((val = Serial.read()) == 10) {   // check for header
     bytesread = 0;
     while(bytesread<10) {              // read 10 digit code
       if( Serial.available() > 0) {
         val = Serial.read();
         if((val == 10)||(val == 13)) { // if header or stop bytes before the 10 digit reading
           break;                       // stop reading
         }
         code[bytesread] = val;         // add the digit          
         bytesread++;                   // ready to read next digit  
       }
     }
     if(bytesread == 10) {              // if 10 digit read is complete
       Serial.print("TAG code is: ");   // possibly a good TAG
       Serial.println(code);            // print the TAG code
     }
     bytesread = 0;
          delay(500);                       // wait for a second
   }
 }
}

// extra stuff
// digitalWrite(2, HIGH);             // deactivate RFID reader



Does anyone know how I might toggle between 9600, and 2400 for the PRFID ?



Daniel

hey

do you mean running two peripherals on the same pin, at different baud rates? Sounds like trouble... some characters sent slow may look like valid data to the fast connection, and vice-versa. You might have to add a gate or something like a CD4066 to selectively connect and disconnect the serial form each device.

D

John_Ryan

yeah, unfortunately that's exactly what I meant.

So there's no way to toggle the baud rates on the Arduino?

Or, can the PRFID work at 9600 baud? I couldn't find a spec sheet. The reason I need it to work on the Arduino, is the troublesome out-of-Arduino processing, inputs are collected by the Arduino, then sent to processing, which posts them via php to a .txt file. The php handles the RFID, not using the PRFID, once it's got a scan it tells processing via the .txt file to tell Arduino to turn a LED on or off.

So, the states of the LEDs can be controlled either by inputs, or server side events. Part of that requires the inputs get paired with the RFID number that's scanned.

If I could get the PRFID working inside Arduino, it'll help trim back on the processing side, which has a few bugs that aren't likely to get resolved anytime soon.


John_Ryan

Ah, ok, so I found the spec sheet. It communicates at 2400 baud and can't be changed.

:'(

John_Ryan

So, I've changed the baud rate to 2400, and cut the value of the debounce in half, and it works fine.

Now that's established, I can operate the PRFID at 2400 baud, this should make for an interesting test :)


John_Ryan

Here's the PRFID code integrated. When one of the switches is turned on, a reading from the RFID scanner is taken.


Code: [Select]

int latchPin = 8;  //Pin connected to ST_CP of 74HC595
int clockPin = 12; //Pin connected to SH_CP of 74HC595
int dataPin = 11; //Pin connected to DS of 74HC595

int inplatchPin = 10; //Pin connected to ST_CP of 7021
int inpdataPin = 9; //Pin connected to SH_CP of 7021
int inpclockPin = 7; //Pin connected to DS of 7021

int rfidPin = 2; //Pin connected to PRFID

char code[10];
int bytesread = 0;
int checkRFID=0;

int sentSwitch = 2;
//Define variables to hold the data
//for shift register.
//starting with a non-zero numbers can help
//troubleshoot
byte switchVar1 = 72;  //01001000
byte lowcBitNum = 7;
byte dBitNum = 6;
byte eBitNum = 5;
byte fBitNum = 4;
byte gBitNum = 3;
byte aBitNum = 2;
byte bBitNum = 1;
byte highcNum = 0;
boolean dBit;
long time = 0;
long debounce = 8000; // big long debounce

int firstByte;
int secondByte;
int thirdByte;
int val;
int serialInArray[4];
int serialCount = 0;

void setup() {
     //set pins to output because they are addressed in the main loop
     pinMode(latchPin, OUTPUT);
     //define pin modes
     pinMode(inplatchPin, OUTPUT);
     pinMode(inpclockPin, OUTPUT);
     pinMode(inpdataPin, INPUT);
     pinMode(rfidPin,OUTPUT);   // Set digital pin 2 as OUTPUT to connect it to the RFID /ENABLE pin
     Serial.begin(9600);
}

void loop() {
     digitalWrite(inplatchPin,1);  //Pulse the latch pin / collect parallel data
     delayMicroseconds(20);
     digitalWrite(inplatchPin,0); //set it to 0 to transmit data serially

     //collect each shift register into a byte

     if (millis() - time > debounce) {

           switchVar1 = shiftIn(inpdataPin, inpclockPin);

           if (getBit(switchVar1, highcNum)) {
                 Serial.println("0");
                 time = millis();
                 checkRFID=1;
           }
           if (getBit(switchVar1, bBitNum)) {
                 Serial.println("1");
                 time = millis();
                 checkRFID=1;
           }
           if (getBit(switchVar1, aBitNum)) {
                 Serial.println("2");
                 time = millis();
                 checkRFID=1;
           }
           if (getBit(switchVar1, gBitNum)) {
                 Serial.println("3");
                 time = millis();
                 checkRFID=1;
           }
           if (getBit(switchVar1, fBitNum)) {
                 Serial.println("4");
                 time = millis();
                 checkRFID=1;
           }
           if (getBit(switchVar1, eBitNum)) {
                 Serial.println("5");
                 time = millis();
                 checkRFID=1;
           }
           if (getBit(switchVar1, dBitNum)) {
                 Serial.println("6");
                 time = millis();
                 checkRFID=1;
           }
           if (getBit(switchVar1, lowcBitNum)) {
                 Serial.println("7");
                 time = millis();
                 checkRFID=1;
           }
 
     }

 if (Serial.available() > 0) {
     serialInArray[serialCount] = Serial.read();
     serialCount++;
     if (serialCount > 3 ) {
           firstByte = serialInArray[1];
           secondByte = serialInArray[2];
           thirdByte = serialInArray[3];
           digitalWrite(latchPin, 0);      // ground latchPin and hold low during transmit
           shiftOut(dataPin, clockPin, firstByte);
           shiftOut(dataPin, clockPin, secondByte);
           shiftOut(dataPin, clockPin, thirdByte);      
           digitalWrite(latchPin, 1);      // return the latch pin high to signal chip that it no longer needs to listen for information
           serialCount = 0;
           sentSwitch = 2;

           // finished with LED's - now see if we're reading from PRFID

           if (checkRFID > 0)      {                         // if not zero then yes
                 digitalWrite(rfidPin, LOW);                  // Activate the RFID reader
                 if(Serial.available() > 0)      {            // if data available from reader
                       if((val = Serial.read()) == 10)      {      // check for header
                             bytesread = 0;
                             while(bytesread<10)      {      // read 10 digit code
                                   if( Serial.available() > 0)      {
                                         val = Serial.read();
                                         if((val == 10)||(val == 13))      {      // if header or stop bytes before the 10 digit reading
                                         break;                  // stop reading
                                                     }
                                   code[bytesread] = val;      // add the digit            
                                   bytesread++;            // ready to read next digit  
                                               }
                                         }
                                   if(bytesread == 10)      {      // if 10 digit read is complete
                                   Serial.print("TAG code is: ");      // possibly a good TAG
                                   Serial.println(code);            // print the TAG code
                                         }
                                   bytesread = 0;
                                   }
                             }
                       digitalWrite(rfidPin, HIGH);      // deactivate RFID reader
                       checkRFID=0;            // return state to zero
                 } // Finished with reader

           }
     }
}
////// ----------------------------------------shiftOut function
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
 int i=0;
 int pinState;
 pinMode(myClockPin, OUTPUT);
 pinMode(myDataPin, OUTPUT);
 digitalWrite(myDataPin, 0);
 digitalWrite(myClockPin, 0);
 for (i=7; i>=0; i--)  {
   digitalWrite(myClockPin, 0);
   if ( myDataOut & (1<<i) ) {
     pinState= 1;
   }
   else {
     pinState= 0;
   }
   digitalWrite(myDataPin, pinState);
   digitalWrite(myClockPin, 1);
   digitalWrite(myDataPin, 0);
 }
 digitalWrite(myClockPin, 0);
}
////// ----------------------------------------shiftIn function
byte shiftIn(int myinpDataPin, int myinpClockPin) {
 int inpi;
 int inptemp = 0;
 int inppinState;
 byte myinpDataIn = 0;
 pinMode(myinpClockPin, OUTPUT);
 pinMode(myinpDataPin, INPUT);
 for (inpi=7; inpi>=0; inpi--)
 {
   digitalWrite(myinpClockPin, 0);
   delayMicroseconds(0.2);
   inptemp = digitalRead(myinpDataPin);
   if (inptemp) {
     inppinState = 1;
     myinpDataIn = myinpDataIn | (1 << inpi);
   }
   else {
     inppinState = 0;
   }
   digitalWrite(myinpClockPin, 1);
 }
 return myinpDataIn;
}
////// ----------------------------------------getBit
boolean getBit(byte myVarIn, byte whatBit) {
 boolean bitState;
 bitState = myVarIn & (1 << whatBit);
 return bitState;
}

John_Ryan

#27
Aug 27, 2007, 02:58 pm Last Edit: Aug 27, 2007, 07:28 pm by John_Ryan Reason: 1
Small problem, the board I've got is a Phidgets USB RFID reader, and it doesn't have a helpful spec sheet.

Are there any other 4100-4102 125khZ 1.6mH options besides the Parallax? The board price is ok, but their shipping price is an absolute rip-off. Many of their distributors sites also don't work, or don't take online sales.

Ideas?


John_Ryan

So I've found a Parallax distributor and ordered a reader, I should have a chance to test the code in a couple of days. In the meantime, I'll start work on the "595 LED micro-boards", I'll post pic's once soldered up and working.

John_Ryan

Parallax arrived. At the moment it's looking like I can't have my RFID and eat my LED's to.

But, the reader and RFID code works, and inputs too, so that's a good start  :)

Go Up