Pages: [1]   Go Down
Author Topic: MAC OS X c++ question  (Read 2225 times)
0 Members and 1 Guest are viewing this topic.
Orlando, FL
Offline Offline
Full Member
***
Karma: 0
Posts: 155
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey guys and girls I'm tring to send a simple "H" to the arudino board via a C++ project i'm working on.  I'm using the serial read example file where sending an "H" turns on pin 13 for a moment and then turns it back off.  here is my code so far.  My problem is I keep returning -1 and never opens connection to the board.  I am using the same port call in Z-Term and Arduino though and they are responding great.   :exclamation :exclamation :exclamationMy code could be all wrong for all I know.  If anyone ahs had success doing this on a mac please let me know.  

Code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>

#include <stdlib.h>
#include <syslog.h>
#include <signal.h>

#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>

#include <IOKit/IOKitLib.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/ps/IOPSKeys.h>
#include <IOKit/ps/IOPowerSources.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/hid/IOHIDKeys.h>
#include <IOKit/hid/IOHIDLib.h>

#include <IOKit/serial/IOSerialKeys.h>
#include <IOKit/IOBSD.h>
using namespace std;

void init_port(int *fd, unsigned int baud)
{
    struct termios options;
    tcgetattr(*fd,&options);
    switch(baud)
    {
       case 9600: cfsetispeed(&options,B9600);
cfsetospeed(&options,B9600);
break;
       case 19200: cfsetispeed(&options,B19200);
cfsetospeed(&options,B19200);
break;
       case 38400: cfsetispeed(&options,B38400);
cfsetospeed(&options,B38400);
break;
  default:cfsetispeed(&options,B9600);
cfsetospeed(&options,B9600);
break;
    }
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    tcsetattr(*fd,TCSANOW,&options);
}

int main()
{
      int fd;      
      fd = open("/dev/ttl.usbserial-3B1", O_RDWR | O_NOCTTY | O_NDELAY);
    if(fd == -1)
    perror("open_port: unable to open port");
      
      init_port(&fd,9600);         //set serial port to 9600,8,n,1
      write(fd, "H", 1);
  return (0);
}
« Last Edit: September 27, 2006, 12:41:14 am by stealthtransam » Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 12
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Very silly question: are you sure the serial port name contains "ttl" and not "tty"?
Logged

Orlando, FL
Offline Offline
Full Member
***
Karma: 0
Posts: 155
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thats a good questions now isn't it.  It seams Z term doesn't know the difference between ttl and tty.  But if i change it to a TTY everything works great.  Thanks i knew i was over looking something stupid.

Logged

Orlando, FL
Offline Offline
Full Member
***
Karma: 0
Posts: 155
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

got it up and running and made a few cool programs The code is on my web page for anyone to use .  I compiled it under GCC on a Mac so it should be good on any platform if you compile it using GCC.

http://web.mac.com/miked13/iWeb/Arduino/
« Last Edit: September 27, 2006, 10:02:01 pm by stealthtransam » Logged

0
Offline Offline
God Member
*****
Karma: 0
Posts: 731
skcor oniudrA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This thread is old, but its "up there" if you happen to be searching for c++, and it stands out on the radar if you also happen to be looking for "OSX" c++

Unfortunately, its also "incomplete", so I've added a routine to "read" from the serial port, as well as write to it.

This has been tested on OSX 10.3.9 - Xcode 1.2

This program works with a version of my "Toggle LED" sketch.  

First, it sends a chr(10) handshake to Arduino (write(fd, "\n", 1)).
Then you have the option of sending:-
write(fd, "0", 1); // Turns the LED OFF
write(fd, "1", 1); // Turns the LED ON
write(fd, "2", 1); // Asks Arduino to Send the value state of the LED
Finally, we send a chr(13) to tell Arduino we've finished talking to it (write(fd, "\r", 1)).

The program automatically starts reading from the serial port after writing to it, if nothing comes back, then it times out after about half a second. The value of the timeout depends on how much of a delay you used in the Arduino sketch between the time the data is received and when a reply is sent back plus it gives the port a chance to receive data before deciding nothing will arrive. This can be tweaked if your running a loop, so if the value of the serial buffer is greater than 0, then you would do a read without using a time out.

To get the name of the USB serial port, you can open Terminal, then type:-

ls /dev/tty.*

Edit copy the name, and change this line of code:-

fd = open("/dev/tty.usbserial-A4001nU7", O_RDWR | O_NOCTTY | O_NDELAY);
 

Code:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>  
#include <termios.h>
#include <iostream>
using namespace std;
volatile int STOP=FALSE;
unsigned char buf[255];
int res;
int myCount=0;
int maxCount=10000;            // Number of cycles to time out serial port
void init_port(int *fd, unsigned int baud)
{
    struct termios options;
    tcgetattr(*fd,&options);
    switch(baud)
    {
            case 9600: cfsetispeed(&options,B9600);
                  cfsetospeed(&options,B9600);
                  break;
            case 19200: cfsetispeed(&options,B19200);
                  cfsetospeed(&options,B19200);
                  break;
            case 38400: cfsetispeed(&options,B38400);
                  cfsetospeed(&options,B38400);
                  break;
            default:cfsetispeed(&options,B9600);
                  cfsetospeed(&options,B9600);
                  break;
    }
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    tcsetattr(*fd,TCSANOW,&options);
}

int main()
{
      int fd;
      fd = open("/dev/tty.usbserial-A4001nU7", O_RDWR | O_NOCTTY | O_NDELAY); // List usbSerial devices using Terminal ls /dev/tty.*
      
    if(fd == -1) {                        // Check for port errors
            cout << fd;
            perror("Unable to open serial port\n");
            return (0);
      }
      
      cout << "Serial Port is open\n";
      
      // Write to Serial Port
      init_port(&fd,9600);                  //set serial port to 9600,8,n,1
      write(fd, "\n", 1);                  // chr(10) start comms
      write(fd, "2", 1);                  // 0 = off 1 = on 2 = ask LED state
      write(fd, "\r", 1);                  // chr(13) terminate comms
      cout << "Write to serial port OK\n";
      
      // Read from Serial Port
      while (STOP==FALSE) {
            myCount++;
            res = read(fd,buf,1);
            buf[res]=0;
            if (buf[0]==13) {            // Stop reading serial port if value = 13
                  STOP=TRUE;
            }
            if (buf[0]!=13) {            // If value = 13 then don't display it
                  if (buf[0]>0) {            // If received greater than 0, display it
                        std::cout << "Led Value is: " << (int)buf[0]<< std::endl;
                        myCount=0;      // Byte received so reset timer
                  }
            }
            if (myCount>maxCount) {         // Stop reading port if time out
                  STOP=TRUE;
                  myCount=0;
                  cout << "Serial Port Timed Out\n";
            }
      }
      close(fd);                              // Close the Serial Port
      return (0);                              // End program
}

Here is the Arduino Code

Code:
/*
 * Toggle LED via c++
 */

int incomingByte = -1;
int ledPin = 13;                // LED connected to digital pin 13
int  val = 0;
char code[10];
int bytesread = 0;
int led1 = 1; // LED initial state is ON

void setup()                    // run once, when the sketch starts
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
  Serial.begin(9600);
  digitalWrite(ledPin, HIGH);   // sets the LED on
}

void loop()        {             // run over and over again
  checkSerial();
}

void checkSerial() {
  if(Serial.available() > 0) {          // if data available
    if((val = Serial.read()) == 10) {   // check for header start
      bytesread = 0;
      while(bytesread<1) {              // read 1 digit code
        if( Serial.available() > 0) {
          val = Serial.read();
          if(val == 13) { // check for header end  
            break;                       // stop reading
          }
          code[bytesread] = val;         // add the digit          
          bytesread++;                   // ready to read next digit  
        }
      }
      if(bytesread == 1) {              // if 1 digit read is complete
        incomingByte = int(code[0]);
        doLEDS();
      }
      bytesread = 0;
      delay(50);                       // wait for a second
    }
  }


}

void doLEDS()
{

  if (incomingByte == 49) {
    digitalWrite(ledPin, HIGH);    // sets the LED off
    led1=1;
  }

  if (incomingByte == 48) {
    digitalWrite(ledPin, LOW);    // sets the LED off
    led1=0;
  }
  
  if (incomingByte == 50) { // php is asking for the LED state
      Serial.print(led1);
      Serial.print char(13);
  }
  
}
Logged

0
Offline Offline
God Member
*****
Karma: 0
Posts: 731
skcor oniudrA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I thought it also worth mentioning that its possible to run c++ applications from php using the PHP exec() function.

We can also use the passthru PHP function to execute a $command variable as an external Unix program and pass the raw output back to the web browser, like so:-

$command = "/Applications/Mamp/htdocs/CppApp " . escapeshellcmd($args);
passthru($command);

If you already have the g++ complier then you don't need to use Xcode, though Xcode works just as well I've tested both.

Using the sample c++ code above, you can copy it into a text editing program, and save it in your htdocs directory as CppApp.cpp

Open terminal, and type
which g++

This will display the path to g++, if you don't have it you can search google for a version for your platform and download it.

In terminal, change into the directory where you saved the CppApp.cpp file, using "cd", in my case, that looked like this:-

cd '/Applications/Mamp/htdocs/'

Now use the G++ compiler to compile the .cpp file into an object file containing machine code. Use the G++ command like this:

g++ -c CppApp.cpp

If you check the directory you'll see that a CppApp.o has been created which is the machine code version of the cpp file, and now we want to create an executable file from that object file like this:-

g++ CppApp.cpp –o CppApp

This creates a new executable file named "CppApp". Unix executables do not have extensions.

The executable can now be run from php using the methods described above.

This offers another method of controlling Arduino over www over USB without needing to use an ethernet shield.

I use MAMP with Apache php 5 and mysql installed on OSX 10.3.9. With an Arduino NG connected over USB.

Its possible to pass variables to the executable and read results back through the browser window using php, so it could be used with writing sensor data back to a mySql database ... I discovered thats a lot easier to do using php than it is using c++ =)

Logged

Pages: [1]   Go Up
Jump to: