Shop OBEX P1 Docs P2 Docs Learn Events
raspberry pi and propellor — Parallax Forums

raspberry pi and propellor

Patrick222122Patrick222122 Posts: 30
edited 2013-01-20 11:58 in Propeller 1
Has anyone got a propeller and a Raspberry pi to communicate with each other yet. I have tried several methods myself and have not succeed. First I tried usb using libusb for c with no success. Now I am trying serial using the pi inbuilt uart port. If anybody has acheive what I am trying to do, please reply with detailed instructions on how
«1

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2013-01-12 11:06
    USB way works fine!

    You should tell us which programming language you want to use on the RasPi. Anyway, here is an example in C:
    #include <unistd.h>
    #include <string.h>
    #include <stdio.h>
    #include <termios.h>
    #include <sys/fcntl.h>
    
    int main( int argc, char *argv[] )
    {
       struct termios termOptions;
       char           port[1024];
       int            ttyFid;
       
       if( argc == 2 )
         {
    	strcpy( port, argv[1] );
    	printf( "Read port name: %s\n", port );
         }
       else
         {
    	printf( "Usage: setSer /dev/ttyUSB0\n" );
    	return -1;
         }
       
       ttyFid = open( "/dev/ttyUSB0", O_RDWR );
       if (ttyFid == -1)
         {
    	printf( "Error unable to open port!\n" );
    	return -1;
         }
       
       tcgetattr( ttyFid, &termOptions );
       
       cfsetispeed( &termOptions, B230400); // 57600 // B115200 ); // B230400 );
       cfsetospeed( &termOptions, B230400); // 57600 // B115200 ); // B230400 );
       
       tcsetattr( ttyFid, TCSANOW, &termOptions );
       
       char ch;
       int  n=0;
       while( 1 )
         {
    	read( ttyFid, &ch, sizeof( ch ) );
    	write( ttyFid, &ch, sizeof( ch ) );
    	if( n%10000 == 0)
    	  printf( "%d\n",n );
    	n++;
         }
       
       close( ttyFid );
    }
    
    In other languages it should be similar, you simply have to open device /dev/ttyUSB0, set it to the same transfer-Speed as the propeller-code and send/receive whatever you want.

    Here is the Propeller code:
    CON
      _CLKMODE      = XTAL1 + PLL16X
      _XINFREQ      = 5_000_000
    
    OBJ
      serial: "FullDuplexSerial"
    
    VAR
      long stack1[20]
      long stack2[20]
      long time
      byte o
      
    PUB PiSerial
      serial.start(31, 30, 0, 230400) '57600 ' 115200) ' 230400)
      
      time := cnt + clkfreq * 30
      cognew( receiver, @stack1 )
      cognew( sender, @stack2 )
      
    PUB sender
      waitcnt( time )
      repeat
        serial.tx( $A5 )
    
    PUB receiver
      dira[16..23]:=$ff
      o:=1
      outa[16..23]:=o
      
      waitcnt( time )
      repeat
        time := serial.rx
        if time<>$A5
          o++
          outa[16..23]:=o
    

    Everything has been tested with a Raspberry and a Quickstart. The stuff has been compiled on the RasPi and the Software has been uploaded to the Propeller by the Pi. I have to search for the thread where I uploaded Compiler and upload-tool.
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-13 07:59
    I am going to be programming in c for here on out. THanks for the code but I still have a few questions regarding the code. The c program is very under documented and I am not familiar with three of the libraries in but I think I understand the code except for the read and write line. I am assuming that ch is the data being transferred but I have never seen a variable with an & procceding it. Also with the spin code I am confused on how to send data for the sender method lacks any parameters.
  • Heater.Heater. Posts: 21,230
    edited 2013-01-13 08:07
    ch is a char (a single byte)

    The read/write functions take the address to an array of bytes as a the data to read/write and a length parameter.
    The & gets you the address of whatever variable, in this case the address of the ch byte. The length is sizeof(ch) which is one.

    Note the name of an array is a pointer in C. So writing &someArray[0] is the same as writing just someArray.

    I have not had any problems using serial comms to the Prop in C or other languages.
    I have also used the UART on the GPIO port. Which is /dev/ttyAMA0 although to use that nicely it's best to stop Linux using it as the console port first.
  • Heater.Heater. Posts: 21,230
    edited 2013-01-13 08:10
    Oh and welcome to the forum.

    We also have propgcc running on the Raspi if you want to develop on the Pi, no PC required.
    I have a customized propeller loader that uses the on board UART if you don't want to mess with USB Serial adapters.
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-13 09:15
    well I ran the program and I think I got a working connection. I think it is time I clued you in on what exactly I am trying to do. I am add my pi to robot I am building to allow it to do certain high level processing jobs such as vision. The propeller will control basic navigation and controlling the motors. I may need a hand turning the above code(especially the spin code into control programs, so keep the advice coming
  • MagIO2MagIO2 Posts: 2,243
    edited 2013-01-13 11:16
    Well .. yes .. no comments in my code, that's because it was only meant as a quick test. I used it to connect a quickstart and a raspberry. The quickstart is sending single bytes and the raspberry echos those back to the propeller. The propeller is then checking and if there is a missmatch it shows up on the LEDs of the quickstart.
    So, this code of course only gives you the basics.

    You should come up with concrete questions rather than asking for unspecific advice.

    High level only means it supports the propeller, or does it mean in the end the raspberry will be the brain? In other words, who is going to be the master?
    The point is, that I'd implement something like a command-loop on the slave-side. As long as there is no problem with transmission-speed, I'd always send commands and parameters in ASCII-text, because then you can "listen" on the transmissions and see what is going on. This of course needs some conversion routines which converts for example longs into strings and on the other side you have to convert the string back to a long, but you can also test the stuff with a terminal program first.
  • KeithEKeithE Posts: 957
    edited 2013-01-13 11:51
    Heater. wrote: »
    Oh and welcome to the forum.

    We also have propgcc running on the Raspi if you want to develop on the Pi, no PC required.
    I have a customized propeller loader that uses the on board UART if you don't want to mess with USB Serial adapters.

    Heater where's the best place to look for information on the Raspi propgcc and customized loader? Have you considered sending a brief writeup to TheMagPi magazine?

    Edited to add - it would be cool to support RISC OS as well. The basic on there lets you mix a nice basic with ARM assembly.
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-13 12:22
    the pi will the master. The prop is being used mainly to pulse the servos I use as drive motors and some of the basic navigating. Every other behavior will done by the pi such as following a blob of a certain color. I do nee a hand with modifying the propeller code specifically the receiver method. I need to modify it to return a value.
  • Heater.Heater. Posts: 21,230
    edited 2013-01-13 13:13
    A ready made package with SimpleIDE and propgcc is linked from the first post in this thread:
    http://forums.parallax.com/showthread.php/141469-SimpleIDE-for-Raspberry-Pi-Raspian

    Here is a thread describing how to build propgcc on the Pi:
    http://forums.parallax.com/showthread.php/141428-propgcc-builds-on-Raspberry-Pi-!!

    And here is one re: the SimpleIDE build on the Pi:
    http://forums.parallax.com/showthread.php/141429-SimpleIDE-builds-on-the-Raspberry-PI-!!

    A ready made package with SimpleIDE and propgcc linked from the first post in this thread:
    http://forums.parallax.com/showthread.php/141469-SimpleIDE-for-Raspberry-Pi-Raspian

    I did think about a little note for MagPi, perhaps if time permits.

    I suspect building propgcc under RiscOS might be fraught with problems.
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-14 07:47
    Well i got the pi side all sorted out with a simple modification to the c code above that should suffice until I start working with open CV. I plan to start work on the propeller end after work. I think I should have mentioned earlier that this is the first time I have ever worked with multi-cog processing on the propeller so don't be surprised if I ask some silly questions.
  • Bill HenningBill Henning Posts: 6,445
    edited 2013-01-14 10:20
    Thanks for posting those links Heater!

    I finally received my R2.0 Raspberry pi's about a week ago - really neat little boards.
    Heater. wrote: »
    A ready made package with SimpleIDE and propgcc is linked from the first post in this thread:
    http://forums.parallax.com/showthread.php/141469-SimpleIDE-for-Raspberry-Pi-Raspian

    Here is a thread describing how to build propgcc on the Pi:
    http://forums.parallax.com/showthread.php/141428-propgcc-builds-on-Raspberry-Pi-!!

    And here is one re: the SimpleIDE build on the Pi:
    http://forums.parallax.com/showthread.php/141429-SimpleIDE-builds-on-the-Raspberry-PI-!!

    A ready made package with SimpleIDE and propgcc linked from the first post in this thread:
    http://forums.parallax.com/showthread.php/141469-SimpleIDE-for-Raspberry-Pi-Raspian

    I did think about a little note for MagPi, perhaps if time permits.

    I suspect building propgcc under RiscOS might be fraught with problems.
  • RobotWorkshopRobotWorkshop Posts: 2,307
    edited 2013-01-14 10:52
    MagIO2 wrote: »
    USB way works fine!

    You should tell us which programming language you want to use on the RasPi. Anyway, here is an example in C:

    Everything has been tested with a Raspberry and a Quickstart. The stuff has been compiled on the RasPi and the Software has been uploaded to the Propeller by the Pi. I have to search for the thread where I uploaded Compiler and upload-tool.

    Hello MagIO2,

    Thanks for posting your example! I was just getting ready to try something similar and your example should give me a head start.

    Robert
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-15 10:28
    bad news I tried my modified code and it does not work. I am uploading both programs in the hopes you will know what I did wrong
    #include <unistd.h>
    #include <string.h>
    #include <stdio.h>
    #include <termios.h>
    #include <sys/fcntl.h>
    
    
    int main(int argc,char* argv[])
    {
    struct termios termOptions;
    char port [1024];
    int ttyFid;
    
    
    ttyFid = open("/dev/ttyUSB0",O_RDWR);
    
    
    tcgetattr(ttyFid,&termOptions);
    
    
    cfsetispeed(&termOptions,B230400);//57600//B115200);//B230400);
    cfsetospeed(&termOptions,B230400);//57600//B115200);//B230400);
    
    
    tcsetattr(ttyFid,TCSANOW,&termOptions);
    char go;
    char ch;
    int n=0;
    while(1)
    {
    read(ttyFid,&ch,sizeof(ch));
    printf("%s\n",ch);
    if(ch=='a'){
    go='w';}/*reverse and turn 180 command*/
    else if(ch=='b'){
    go='x';}/*turn left*/
    else if(ch=='c'){
    go='y';}/*turn right*/
    else{
    go='z';}
    printf("%s\n",go);
    write(ttyFid,&go,sizeof(ch));
    if(n%10000==0)
    printf("%d\n",n);
    n++;
    }
    
    
    close(ttyFid);
    }
    
    the prop code will be in the next post
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-15 10:33
    here is the propeller code. The usb object I created from the propeller code sent with the first reply.
    CON
      _CLKMODE      = XTAL1 + PLL16X
      _XINFREQ      = 5_000_000
     ServoCh1 = 5
    ServoCh2 = 15         
    input_pin=16  
    input_pin2=15 
    OBJ
    usb: "usb"
    SERVO : "Servo32v7.spin"
    serial: "FullDuplexSerial"     
    VAR
    byte input
    word output
    pub go
    usb.PiSerial
    SERVO.Start                 'Start Servo handler
    SERVO.Ramp  '<-OPTIONAL     'Start Background Ramping
      dira [input_pin]~
      dira [input_pin2]~
    SERVO.SetRamp(ServoCh1,2000,1)           'Pan Servo
    SERVO.SetRamp(ServoCh2,1000,1)
    repeat
     if ina[input_pin]==0
           serial.tx("a")    
     elseif ina[input_pin2]==0
            serial.tx("b")    
     elseif ina[input_pin]==0 AND ina[input_pin2]==0
            serial.tx("c")    
     elseif ina[input_pin]==1 AND ina[input_pin2]==1 
             serial.tx("d")    
     output:=serial.rx 
     if(output:="w")
       forward
     elseif(output:="x")
       turnleft
     elseif(output:="y")
      turnright
     elseif(output:="z")
      reverse    
    
    
    pri forward
    SERVO.SetRamp(ServoCh1,2000,1)           'Pan Servo
    SERVO.SetRamp(ServoCh2,1000,1)
    pri turnleft
    SERVO.SetRamp(ServoCh1,1000,1)           'Pan Servo
    SERVO.SetRamp(ServoCh2,2000,1)
      waitcnt(125_000_000+cnt)
    SERVO.SetRamp(ServoCh1,2000,1)           'Pan Servo
    SERVO.SetRamp(ServoCh2,2000,1)
    waitcnt(125_000_000+cnt)
    return 
    
    
    pri turnright
     SERVO.SetRamp(ServoCh1,1000,1)           'Pan Servo
    SERVO.SetRamp(ServoCh2,2000,1)
      waitcnt(125_000_000+cnt)
    SERVO.SetRamp(ServoCh1,1000,1)           'Pan Servo
    SERVO.SetRamp(ServoCh2,1000,1)
    waitcnt(125_000_000+cnt)
    SERVO.SetRamp(ServoCh2,1000,1)
    return
    pri reverse
       SERVO.SetRamp(ServoCh1,2000,1)
     SERVO.SetRamp(ServoCh1,1000,1)
    waitcnt(125_000_000+cnt)
    SERVO.SetRamp(ServoCh2,2000,1)           'Pan Servo
    SERVO.SetRamp(ServoCh2,1000,1)           'Pan Servo
    waitcnt(250_000_000+cnt)
    return
    
    
    
  • RobotWorkshopRobotWorkshop Posts: 2,307
    edited 2013-01-15 11:30
    What is the object USB in your code? Can you supply the source for that? In the examples shown that worked it looks like the object FullDuplexSerial was used to talk to the Raspberry Pi through the USB connection. I also didn't see where the baud rate was set on the Propeller end to talk to the Raspberry Pi. You may also want to try a lower baud rate if there isn't a lot of data to send back and forth.

    Robert
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-15 12:09
    The usb object is the spin code from the first reply above. I think it may have been a bad idea to reuse the methods for I belive that it caused the code to not get to the control structure
  • MagIO2MagIO2 Posts: 2,243
    edited 2013-01-15 12:30
    I don't know why you use my code as an object. It's only an example that you should understand and adopt.

    You already added a FullDuplexSerial to your code. The Problem is, that you use it without initializing it. If you would initialize it to use the USB Connection you'd have a Problem with the USB-object, because it is also using those Pins.
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-17 06:07
    Still no luck in getting the pi and propboard talking. i think it is a problem with the c code for all it is outputting is Usage: setSer/dev/ttyUSB0. I am not sure what this means, I think has something with the ports being unavaliable because they are set aside for the OS like the uart port is when the pi arrives from the factory. WHat do you think.
    #include <unistd.h>
    #include <string.h>
    #include <stdio.h>
    #include <termios.h>
    #include <sys/fcntl.h>
    
    
    int main(int argc,char *argv[])
    {
    struct termios termOptions;
    char port[1024];
    int ttyFid;
    
    
    if(argc==2)
    {
    strcpy(port,argv[1]);
    printf("Read por tname:%s\n",port);
    }
    else
    {
    printf("Usage: setSer/dev/ttyUSB0\n");
    return-1;
    }
    ttyFid=open("/dev/ttyUSB0",O_RDWR);
    if(ttyFid==-1){
    printf("Error unable to open port!\n");
    return-1;
    }
    
    
    tcgetattr(ttyFid,&termOptions);
    
    
    cfsetispeed(&termOptions,B230400);//57600//B115200);//B230400);
    cfsetospeed(&termOptions,B230400);//57600//B115200);//B230400);
    
    
    tcsetattr(ttyFid,TCSANOW,&termOptions);
    char go;
    char ch;
    int n=0;
    int i;
    while(1)
    {
    read(ttyFid,&ch,sizeof(ch));
    printf("%s\n",ch);
    if(ch=='a')
    {
    go='w';
    }/*reverse and turn180 command*/
    else if(ch=='b'){
    go='x';
    }/*turn left*/
    else if(ch=='c'){
    go='y';
    }/*turn right*/
    else{
    go='z';
    }
    printf("%s\n",go);
    write(ttyFid,&go,sizeof(ch));
    if(n%10000==0)
    printf("%d\n",n );
    n++;
    scanf("%i",i);
    
    
    if(i==1){
    break;}
    else{
    printf("1");
    }
    }
    
    
    close(ttyFid);
    }
    
  • Heater.Heater. Posts: 21,230
    edited 2013-01-17 07:05
    You have to specify which serial port to use when you run that program. For example type this as the command:

    setSer /dev/tty/USB0

    Assuming your port is USB0.
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-17 09:42
    that's it? I just need to type that command in and nothing else? Which port USB) the top one ore the bottem one
  • Heater.Heater. Posts: 21,230
    edited 2013-01-17 10:23
    I presume when you say "top" or "bottom" you mean sockets on the connector.
    It does not matter.
    If you have only one USB serial device plugged in it should be USB0.
    To be sure use the command "lsusb" and it should tell you what is what.
  • MagIO2MagIO2 Posts: 2,243
    edited 2013-01-17 10:41
    @Patrick222122:
    It looks like you do not really understand the code. And I think I gave you a work in progress or a "stop improving because I checked what I wanted to check with it"-version. Well ... let's explain:
    argc is the number of arguments you pass when calling the program, so the if checks that there is a parameter (besides the program name itself). If you don't give a parameter, you see the usage-message.
    If you give a parameter it is copied as a string to the port-array. This is what you do when you plan to allow calls without parameter and want port to be defaulted to something. This is the part which seems to be unfinished, because when opening the serial interface in any case the hardcoded /dev..USB0 is used. This means that in fact it's currently totally irrelevant which parameter you pass, as long as you pass one.

    You can fix that as an exercise if you want ;o)

    The code itself is only reading a byte and sending it back. If 1000 bytes have been received you'll see an output.

    Now to the propeller code I wrote: It waits for 30 seconds and then starts sending $a5. The other COG is receiving and compares the incoming byte with $a5. When there is a difference, it's counted and the counter value is written to the quickstart LEDs.
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-17 12:17
    SO you are saying that I have to add another Parameter to the main method because the if is checking if there two parameters other than argc? or do I have to set argc=to two to procced
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-17 12:27
    never mind that, you are saying I have to give argc and argv values right? I understand I have to give argc a value of two but what of argv? Right now the port is null isn't it
  • Heater.Heater. Posts: 21,230
    edited 2013-01-17 12:39
    When you run a C program from the command line and give it parameters, for exampe:

    somecommand par1 par2 par3

    Then the main() function gets parameters argc and argv.

    argc is is the number of command line parameters including the command itself. So in the above case argc will be 4.

    argv is an array of pointers to strings. Such that:

    argv[0] is the name of the command itself. In this case "somecommand"

    argv[1] is the first parameter. In this case "par1"

    and so on.

    In the case of the program under discussion, argv[0] is the name of the program, argv[1] is the serial port path and argc is expected to be 2.
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-17 12:48
    didn't know that, most of programming with c I have has been done via Visual C++ for windows. I only started gcc and linux program about a month ago. Well that kind of rise another problem. I want the program to start immeideatly after start up. Could this be acheived?
  • Heater.Heater. Posts: 21,230
    edited 2013-01-17 12:52
    Yes, of course.
    But perhaps you should come back to that when you have everything you want working from the command line first.
  • RobotWorkshopRobotWorkshop Posts: 2,307
    edited 2013-01-18 07:07
    didn't know that, most of programming with c I have has been done via Visual C++ for windows. I only started gcc and linux program about a month ago. Well that kind of rise another problem. I want the program to start immeideatly after start up. Could this be acheived?

    You don't have to use argc and argv if you don't want to. For testing you can hard code the values into your program instead of reading them from the command line. Once it is working you can either leave them hard coded or you could store configuration items in a file and just read the file when your program starts to get the name of the USB ports to use and any other configuration you want to change. Keeping those items in a separate file helps if you want to change them since you won't have to re-compile your program to change them.
  • Patrick222122Patrick222122 Posts: 30
    edited 2013-01-18 14:17
    okay I done like you said and it is working, kind of. I think the problem is that I am not putting in the right usb path as a parameter. Is there any way to find out what it is? I know the device number and the device Id if you are wondering.
  • Heater.Heater. Posts: 21,230
    edited 2013-01-18 15:11
    Just have a look in your dev directory:

    $ ls /dev/tty*

    Should show you the /dev/ttyUSB0 device file.
Sign In or Register to comment.