Pages: [1] 2 3   Go Down
Author Topic: Serial communication with PHP  (Read 17720 times)
0 Members and 1 Guest are viewing this topic.
Atlanta, GA
Offline Offline
Newbie
*
Karma: 0
Posts: 25
Do I smell smoke?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello all,

I've been working with PHP on my home Apache server to make some web enabled Arduino projects.  So far, I've got an Arduino sketch that utilizes a switch statement to toggle three LEDs on and off.  This works perfectly when I upload the sketch and use the serial monitor to send the characters 'a', 'b' or 'c' (minus the single quotes).

Now I'm attempting to send the same characters to the USB serial port via PHP to do the same thing but I'm getting no love.  Can anyone take a look at both my Arduino and PHP code and give me some pointers to make this a reality?  I'd really appreciate the help!

My stolen and modified Sketch:
Code:
/*
Set 3 LEDs, (Red, Yellow, Green) on pins 2, 3 and 4
Open the serial monitor and send the characters a, b or c to toggle the
LEDs on or off
 */

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
  // initialize the LED pins:
  for (int thisPin = 2; thisPin < 5; thisPin++) {
    pinMode(thisPin, OUTPUT);
  }
}
int redState=0;
int yellowState=0;
int greenState=0;
void loop() {
  // read the sensor:
  if (Serial.available() > 0) {
    int inByte = Serial.read();
    // do something different depending on the character received.  
    // The switch statement expects single number values for each case;
    // in this exmaple, though, you're using single quotes to tell
    // the controller to get the ASCII value for the character.  For
    // example 'a' = 97, 'b' = 98, and so forth:

    switch (inByte) {
    case 'a':    
      if (redState==0){
        digitalWrite(2, HIGH);
        redState=1;
      }else{
        digitalWrite(2, LOW);
        redState=0;
      }
      break;
    case 'b':
    if (yellowState==0){
     digitalWrite(3, HIGH);
     yellowState=1;
    }else{
      digitalWrite(3, LOW);
      yellowState=0;
    }
      break;
    case 'c':    
    if (greenState==0){
     digitalWrite(4, HIGH);
     greenState=1;
    }else{
      digitalWrite(4, LOW);
      greenState=0;
    }
      break;
    default:
      // turn all the LEDs off:
      for (int thisPin = 2; thisPin < 5; thisPin++) {
        digitalWrite(thisPin, LOW);
      }
    }
  }
}

And one of my PHP toggle scripts:
Code:
<?PHP

$fp =fopen("com7", "w");
fwrite($fp, chr(a));
fclose($fp);

?>

Anyone got any ideas?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48556
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

When the Arduino IDE opens the Serial Monitor, the Arduino resets. When the Serial Monitor is closed, the Arduino resets.

It's possible that opening and closing the serial port using PHP causes the same thing to happen.

Try adding some code in setup that flashes all 3 LEDs three times.

Then, run the PHP script and see if the LEDs start flashing. Let us know what happens, please.
Logged

Atlanta, GA
Offline Offline
Newbie
*
Karma: 0
Posts: 25
Do I smell smoke?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Well I did that by changing the switch statement in the code above to this:

Code:
switch (inByte) {
    case 'a':    
    digitalWrite (2, HIGH);
    delay (1500);
    digitalWrite (2, LOW);
    delay (1500);
    digitalWrite (2, HIGH);
    delay (1500);
    digitalWrite (2, LOW);
    delay (1500);
    digitalWrite (2, HIGH);
    delay (1500);
    digitalWrite (2, LOW);
    break;

Once again, when I use the serial monitor and I send 'a' (without the single quotes) the LED on pin 2 flashes on for 1.5 seconds and off again 3 times.  Works exactly as expected.  But when I use PHP to send the 'a' (using the code above, I can see the TX and RX LEDs on the board flash once, and the L LED flashes (because I'm assuming it flashes when it reads serial incoming data), but the LED on pin 2 stays unaffected.  I also tried sending chr(97) using PHP because that's the ASCII representation for 'a'.  I even tried sending raw 'a' and raw 97 (without the chr() function) and it still doesn't work.  Surely this isn't that complicated!  Help?!
Logged

Atlanta, GA
Offline Offline
Newbie
*
Karma: 0
Posts: 25
Do I smell smoke?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Of course, I must make you aware that I am on a Windows XP pro OS, so I'm not sure if there are some jerky Windows issues included w/ this or not...  Just trying to give you all as much info as I can.

Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 61
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you know for certain that your PHP script/PHP setup is working properly? Have you tried a null-modem or loopback to verify that something is coming out of the COM port? Have you checked your PHP logs for errors?
Logged

Lincoln, NE
Offline Offline
Full Member
***
Karma: 0
Posts: 106
Having lots of fun with Arduino. Thanks everyone!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
I tried sending this via private message yesterday, but maybe I didn't send it correctly.

I don't know PHP, but shouldn't the character 'a' be in quotes in your PHP code?
Instead of this: fwrite($fp, chr(a));
try this: fwrite($fp, "a"));
or this: fwrite($fp, chr(97));

Good luck!
Logged

Atlanta, GA
Offline Offline
Newbie
*
Karma: 0
Posts: 25
Do I smell smoke?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

cr0sh2:

Yea, I'm pretty sure that PHP is sending data to the serial port.  I wrote a simpler script to test if it was even sending data at all.  It looks like this:

Code:
void setup(){
 
 Serial.begin(9600);
 pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
}
 void loop(){
  
  if (Serial.available() > 0) {
   digitalWrite(2, HIGH);
   delay(1500);
   digitalWrite(2,LOW);
   delay(1500);
  
    
  }else{
    digitalWrite(3, HIGH);
    delay(1500);
    digitalWrite(3, LOW);
    delay(1500);
    
  }
 }

Then I launch the same PHP script as in my initial post, and the LED starts blinking.  So I know PHP is sending data.  The problem exists that I don't know exactly what PHP is sending, and I don't know exactly how Arduino is interpreting what PHP is sending.  

I've tried using the chr() function in PHP, I've tried omitting that function, I've used single quotes and double quotes, I've tried sending just the ASCII number for the corresponding Switch statements.  I've pulled my hair out, and drank myself into a coma.  No ideas yet.  And unfortunately, scouring the web for "PHP to Arduino" doesn't seem to show me any people who've had similar difficulties.  Everyone else seems to get this up and running with little to no difficulties.  Anyone else have some ideas?
Logged

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is a free serial port monitoring application called PortMon out on the net that will show exactly what is being sent and received on the computer serial port (I use it fairly often). I'm new to this forum and am curious as to the apparent love affair with PHP. Seems it is not well suited for serial port operations.
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48556
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

PHP plays well with MySQL and Apache, all of which are free.

All of which were also first developed on Linux, and then ported to Windows.

The problem with PHP and serial port communication is with the underlying Microsoft code that is the real interface with the psuedo-serial port via USB that is used today.

And, of course, the limited ability to debug applications on the Arduino.

@soup

I wonder what happens if you send more than one character to the Arduino from PHP. Try sending it a long string. Make the LED blink when you've read a character, not just when there is data to read. Unless you remove the characters from the serial buffer, they will stay there, no matter how many times you call Serial.available().
Logged

0
Offline Offline
Tesla Member
***
Karma: 141
Posts: 9470
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

For out going serial commands I just use apache and notepad made files. For bidirectional serial I've used a simple application made with freebasic. Seems PHP may be more suited to database applications than robotic control. I started out using qbasic to operate my servo pan/tilt cam in 2001 when I got a cable connection, switched to the notepad files in 2003, and still working (below). Simple, but does what I need.

http://web.comporium.net/~shb/wc2000-PT-script.htm
Logged

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   smiley-cool

Atlanta, GA
Offline Offline
Newbie
*
Karma: 0
Posts: 25
Do I smell smoke?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for all the advice.  I feel like I'm close here, but not quite there yet.

So I took zoomkat's advice and downloaded/installed PortMon.  I crank it up and use my little PHP snippet above with the following results:

Code:
0.04127871  Apache.exe      IRP_MJ_CREATE      VCP0      SUCCESS      Options: Overwrite       
0.00092796  Apache.exe      IRP_MJ_WRITE      VCP0      SUCCESS      Length 2: 97      
0.00000343  Apache.exe      IRP_MJ_CLEANUP      VCP0      SUCCESS            
0.11261471  Apache.exe      IRP_MJ_CLOSE      VCP0      SUCCESS            

Now my challenge is deciphering what that exactly means.  There are four lines of results there.  the second line ends with '97' which is an ASCII 'a' (and that's what the PHP code above is sending).  What do the other lines mean?  Could it mean that Windows is sending more than just the ASCII 'a' that I want it to?  Could it be that I'll have to analyze the incoming data on the Arduino byte by byte to parse out the unwanted bits?  

I know I've already said it, but thanks for all of your help and advice.  This might honestly be the best forum I've ever participated in, due largely to the members!  Keep up the good work guys/gals!

Oh, and thanks for being patient w/ me as I learn.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48556
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The third column implies that the connection to the port was made, that some data was written to the port (probably using a buffer), that the buffer was flushed (the data was actually sent), and that the port was closed.

All that should have arrived at the Arduino was the letter 'a'.
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 200
Posts: 12779
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset


IRP - I/O Request Packet; a request sent to an I/O driver
MJ - Major Function Code

CREATE - request to create a handle ("open" for us non-Microsoft / normal folks)
WRITE - fairly obvious
CLEANUP - ditto
CLOSE - close the handle

VCP0 - name of the device (Virtual COM Port 0); "COM7" is the DOS name

"Length 2: 97" - I'm not familiar with PortMon but I assume that to mean two bytes were written: the character "9" (0x39) followed by the character "7" (0x37).
Logged

Atlanta, GA
Offline Offline
Newbie
*
Karma: 0
Posts: 25
Do I smell smoke?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Man I'm totally frustrated at this point.  I really thank you all for your input, but I'm tapped out.  I can't seem to wrap my head around this concept.

Here's my dream:

I recently purchased a crappy USB web cam and I have some servos on the way via mail.

I'd like to build a web enabled pan/tilt camera like zoomkat has with my Arduino, Apache server and some sort of client-side programming language.  My first instinct is to use PHP because I have some experience with it, and it's fairly simple and free.

If I'm able to get the pan/tilt camera working, the next iteration will be a web-enabled Etch-a-Sketch.  I know others have done it, but not me...  Not yet at least smiley-wink

So, I'll get this working eventually, and when I do, I'll make sure to credit all of you in my blog post.

I just have to wonder, if my PortMon results show that I'm sending an 'a' to Arduino, why didn't my initial code work?  It should have!  Dang, I'm frustrated.  Another round of beers my good man!

(p.s., if there are any Atlanta, GA folks here, I'll gladly meet you for a beer if you'll solve my issue, and I'll pay!)

Cheers
Logged

Chile
Offline Offline
Edison Member
*
Karma: 35
Posts: 1251
Arduino rocks?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I have controlled a big led screen using PHP remotely. It is almost the same problem, the way I managed this task is launching a system monitor that is monitoring certain files for changes (in your case for example, angles to update the camera) and this monitor "eats" this files, so php knows if the last instruction is applied.

Problems:
-Apache must allow "interactive" process (apache configuration)
-The monitor should be singleton (just one instance to avoid port sharing issues)
-The monitor should "monitor" files in such an elegant way like the filesystemMonitor object in c# to keep polling out your system

The monitor resides in the www folder (php just 'exec' init_monitor.cmd then edit the bin/screen files):
http://screencast.com/t/Mjc3MTEzODk

The files generated by php contains a special format for each line of the lcd screen, also the delay to send the next one (I use .temp extension files to work first from php because data is extracted from db with some delays and I don't want the monitor opening my files until I copy the final file with .screen extension):
http://screencast.com/t/MDcxYzRh

And voilá, a cute monitor icon with a little eyecandy smiley-wink (it blinks a little while sending a new screen):
« Last Edit: February 03, 2010, 12:18:30 am by eried » Logged

My website: http://ried.cl

Pages: [1] 2 3   Go Up
Jump to: