3

I am trying to send a three digit number from an XCode foundation command-line tool to an arduino over USB as a proof of concept for sending a data stream. The arduino code is supposed to flash a light the number of times that the number in the incoming data is. It works perfectly using the serial monitor in the arduino IDE, but when I try using the Objective-C program, which uses ORSSerialPort, the Rx light flashes on the arduino, indicating that it has received data, but nothing else happens.

Here is the Objective-C code:

#import <Foundation/Foundation.h>
#import <IOKit/IOKitLib.h>
#import "ORSSerialPort.h"
#import "ORSSerialPortManager.h"



int main(int argc, const char * argv[])
{
    @autoreleasepool {

        ORSSerialPort *arduino = [ORSSerialPort serialPortWithPath:@"/dev/tty.usbmodem26231"];
        //initalizes ORSSerialPort instance

        NSString *string = @"012"; //creates string from the 3-digit number

        NSData *outgoingdata = [string dataUsingEncoding:NSASCIIStringEncoding]; 
        //encodes string using ASCII

        int number = 1200;
        NSNumber *baudrate = [[NSNumber alloc] initWithInt:number];
        //initializes an NSNumber for the baud rate

        [arduino open]; //opens port
        baudrate = arduino.baudRate; //sets baud rate
        [arduino sendData:outgoingdata]; //sends data
        [arduino close]; //closes port

        NSLog(@"%@ sent", string); //logs the number
    }   
    return 0;
}

Here is the arduino code:

#include <SoftwareSerial.h>

int i100;
int i10;
int i1;
int total;

void setup() {
  Serial.begin(1200);
  pinMode(2, OUTPUT);
}

void loop() {
int mail = Serial.available(); //reads number of available bytes
  if(mail >= 3) {
    int i100raw = Serial.read()-48; //reads 3 bytes and decodes from ASCII by subtracting 48
    int i10raw = Serial.read()-48;  
    int i1raw = Serial.read()-48; 

    if(i1raw >= 0) {  //checks if each byte is a valid input 
      i100 = i100raw; 
    }
    if(i10raw >= 0) {
      i10 = i10raw; 
    }
    if(i1raw >= 0) {
      i1 = i1raw; 
    }

    total = (i100*100)+(i10*10)+(i1); //puts together 3 digit number from 3 bytes

    while(total > 0) {       //flashes light  
      digitalWrite(2, HIGH);
      delay(50);
      digitalWrite(2, LOW);
      delay(50);
      total--;
    }   
  }
} 
Andrew Madsen
  • 21,309
  • 5
  • 56
  • 97
JP762
  • 31
  • 1

2 Answers2

1

A couple of thoughts:

  1. The main issue is that you're never setting the baudRate for ORSSerialPort. (You have that assignment backwards.) Also, the examples I've seen set the baud rate in ORSSerialPort before opening the port. So, I'd suggest:

    arduino.baudRate = @(1200); //sets baud rate
    [arduino open];             //opens port
    
  2. Also, in my test, if I tried closing the port to the Arduino immediately after writing the data, it would not be received. You might want to wait a bit before closing that port

  3. You might also want to use a new line terminator for what you send to the Arduino. That's obviously a change in both the sending and the receiving code, but it's going to be a little more robust than just reading the next three bytes.

  4. I might also suggest that if you want to be especially careful, you might want to set the delegate for the ORSSerialPort object and implement the ORSSerialPortDelegate methods. There is an error reporting method there that you might want to avail yourself of.

  5. When I begin my Serial on the Arduino, I include a loop that waits for the Serial to connect. The code snippet I took this from says this is only needed with Leonardo only, but it's worth trying if you're finding you cannot successfully receive data when you first open the connection from the Mac side:

    void setup() 
    {
      pinMode(2, OUTPUT);
    
      Serial.begin(1200); 
      while (!Serial) {
        // wait for serial port to connect. Needed for Leonardo only
      } 
    
      Serial.println("OK. Connected.");
    }
    

    Also, when your loop() successfully reads the input from Serial, you can have the Arduino write stuff back (via Serial.println) which you can have you Mac read in order to confirm successful receipt of the data. It's, effectively, a way of affirming receipt of the command and that will help you isolate communication related issues from wiring issues.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Setting the baud rate properly and adding a delay before closing the port haven't solved the problem, currently working on how to integrate a new line terminator – JP762 Mar 14 '14 at 14:17
  • I was wrong in the last comment. I just figured it out that there needs to be a delay after opening the port just like before closing it. – JP762 Mar 14 '14 at 14:27
  • Also, it seems like the delay has to be at least 2 seconds. – JP762 Mar 14 '14 at 14:29
  • heh - was just now writing a reply to suggest you add a delay. Yes, it needs to be a few seconds. There is a way to disable the Arduino reset if that is what you need - or else just add the delay in your Obj-C code. – spring Mar 14 '14 at 14:29
  • FWIW, with my Uno, no delay after opening is needed. Only before closing. But on Leonardo, you have to wait after calling `Serial.begin()`. – Rob Mar 14 '14 at 16:23
  • Very minor note on the first point in this answer: `ORSSerialPort` will happily allow you to set/change the baud rate after opening the port. Of course, it doesn't hurt (and makes more sense, usually) to set it before opening the port. – Andrew Madsen May 11 '15 at 21:47
  • @AndrewMadsen - Agreed. I wasn't trying to make a big deal about that. My point re his having it backwards was that he had `baudrate = arduino.baudRate` instead of `arduino.baudRate = baudrate`. Re setting the baud rate before opening was to merely suggest best practice, but the key point is that he was actually not setting baud rate, but rather just reading it. And that was obviously not his intent. – Rob May 11 '15 at 23:57
  • 1
    @Rob, Sorry, didn't mean to imply that the meat of that point was wrong. The backwards baud rate assignment was indeed obviously the actual problem. I just didn't want people to happen upon this question/answer and think that that limitation on setting baud rate after opening existed. Thanks for the good answer too (I upvoted it back when you originally posted.) – Andrew Madsen May 12 '15 at 14:40
1

Just met same issue and resolved. Set DTR to 1 will probably fix this issue.

arduino.DTR = YES;
Upfly
  • 11
  • 1