Shop OBEX P1 Docs P2 Docs Learn Events
propeller get the sensor data showin the C# ? — Parallax Forums

propeller get the sensor data showin the C# ?

ggg558877ggg558877 Posts: 40
edited 2012-11-02 07:30 in Propeller 1
Hello everyone,
i have used a propeller C3 get the sensor data,
http://i1162.photobucket.com/albums/q535/ggg558877/1_zps95366eda.jpg,
and now i want to show the data in the c#
i have no idea what to do , is there any examples?
thanks
«1

Comments

  • Mike GMike G Posts: 2,702
    edited 2012-10-15 20:23
    Welcome to the forum TW. Your question is a bit broad but a serial connection should do the trick.

    Open source C# serial terminal. Not the greatest but it works and it contains a few good nuggets.
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-15 21:12
    Mike G wrote: »
    Welcome to the forum TW. Your question is a bit broad but a serial connection should do the trick.

    Open source C# serial terminal. Not the greatest but it works and it contains a few good nuggets.

    Nice to meet you, Mike
    now i use a simple example to run in the Parallax-Serial-Terminal,enter any number and it can calculate tangent
    http://i1162.photobucket.com/albums/q535/ggg558877/789.jpg (sorry i don't know how to paste propeller code)
    http://i1162.photobucket.com/albums/q535/ggg558877/555.jpg
    and how can i get the same result in C# serial terminal
    thanks
  • Mike GMike G Posts: 2,702
    edited 2012-10-16 07:04
    The C# Serial terminal does not automatically send a control - line feed chars like PST. Update line 362 of the terminal.cs class to the following.
    string message = !string.IsNullOrEmpty(toSend) ? txtSend.Text + "\r\n" : "Hello World\r\n";
    

    Other than that, enter values in the top textbox and click the send button.

    What is your goal? To learn Spin and C#?
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-16 19:06
    Mike G wrote: »

    What is your goal? To learn Spin and C#?

    Hi, Mike
    My goal just like this video
    http://www.youtube.com/watch?feature=player_embedded&v=JJ1SBgGG11g
    i already get the sensor(AHRS) data in Spin ,and now i want to use C# to receive those data
    but i don't know how to send those data to C#
    sorry this my first to do this
    maybe it's a stupid question
  • JasonDorieJasonDorie Posts: 1,930
    edited 2012-10-17 12:07
    In C# you can just open a serial connection as a data stream and read from it. The fastest way to do it is send the raw data bytes from the Propeller variables. On the C# side you read the bytes out of the stream, assemble them back together into an int, and perform whatever display you want. The simplest way would be to use a Label and set the .Text field of the label to your int value by using the .ToString() operator, like this:
      int myInt = GetIntFromCommStream();  // you'll need to write this function
      lblMyLabel.Text = myInt.ToString();  // Assumes that there's a label on your form, called lblMyLabel
    

    My GroundStation program does all of this, and it's written in C#. You can download it from the top of this thread:
    http://forums.parallax.com/showthread.php?136787-QuadX-my-latest-Propeller-with-Propellers

    The MainForm_Load() function finds all the connected serial ports, picks the one it figures is the connected Propeller chip, and opens it.
    The function GetCommWord() reads two bytes from the serial port and assembles them into a signed short (16 bit) value.

    If you've never used C# before it might be a little overwhelming, but hopefully it's a step in the right direction.

    Jason
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-22 06:20
    thanks Jason I will try it
    now I get a new problem
    I want to send a number from c# to propeller to control the servo and my send buttom code is
       private void btnSend_Click(object sender, EventArgs e)
            {
                // Sends the text as a byte.
                serialPort1.Write(new byte[] { Convert.ToByte(txtDatasend.Text) }, 0, 1);
            }
    
    and propeller code is
    CON
      _xinfreq=5_000_000            
      _clkmode=xtal1+pll16x                 
      
    VAR
      long position             
      long p1                                 
      long Stack[5]                        
    OBJ
    pst : "Parallax Serial Terminal" 
    PUB Demo
        pst.Start(115200)
        p1:=pst.DecIn
        
        cognew(MoveMotor(7),@Stack)           
    
        repeat
         position:=p1                                                                          
         waitcnt(clkfreq+cnt)
    
    
                                                                                                                               
    PUB MoveMotor(Pin) | LowTime,period                  
      dira[Pin]~~                          
      ctra[30..26]:=100                                                                                                                        
      ctra[5..0]:=Pin                                                                
      frqa:=1                                             
      LowTime:=2*clkfreq/100                 
      period:=cnt                           
      repeat
        phsa:=-p1                          
        period:=period+p1+LowTime          
        waitcnt(period)                    
    

    now I send a number 88000 and the propeller tx LED had Blinking but servo have not action
    Can someone please tell me what is my problem
  • Mike GMike G Posts: 2,702
    edited 2012-10-22 07:08
    The value in txtDatasend.text is converted to ASCII. It is not a number. Therefore, 88000 is converted to 5 bytes; $38, $38, $00, $00, $00.

    On the propeller side you must read the 5 bytes and convert the byte array into a number.

    The DecIn command expects the number to terminate with a CR. So add a $13 to the end of txtDatasend.text
    string msg = txtDatasend.text + "\r\n"
    

    You can also send 88000 as a number. 88000 is 3 bytes $01, $57, $C0. On the Propeller side you'll assemble the bytes into a long.
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-22 07:44
    Hi Mike
    how can i read the 5 bytes and convert the byte array into a number on the propeller side
    can you give me some example?
    thanks
  • JasonDorieJasonDorie Posts: 1,930
    edited 2012-10-22 11:23
    It would be much easier (and faster) to convert the text into an integer on the C# side. Use something like this:
    int Value = int.Parse( txtDatasend.Text );
    

    Then, send that integer as 4 bytes, like this:
    serialPort1.Write( (byte)(Value >> 24) );
    serialPort1.Write( (byte)(Value >> 16) );
    serialPort1.Write( (byte)(Value >> 8) );
    serialPort1.Write( (byte)(Value >> 0) );
    

    On the Propeller side, just read the 4 raw bytes out of the stream and reassemble them, like this:
    Value := Pst.rx << 24
    Value |= Pst.rx << 16
    Value |= Pst.rx << 8
    Value |= Pst.rx
    

    The shifting (<< and >>) is to move the bits around. The first shift slides the upper 8 bits down so they're in the low 8-bit position, and then casting to a byte chops off the rest of the number. The other shifts select each subsequent set of 8 bits. On the Propeller side, you receive each set of 8 bits and use the opposite shifts to move them back into the right place, then use the or operator ( | ) to put them back together into a single variable.
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-22 18:44
    JasonDorie wrote: »

    Then, send that integer as 4 bytes, like this:
    serialPort1.Write( (byte)(Value >> 24) );
    serialPort1.Write( (byte)(Value >> 16) );
    serialPort1.Write( (byte)(Value >> 8) );
    serialPort1.Write( (byte)(Value >> 0) );
    

    hi,Jason
    I try this code but he say can't convert string from byte

    and I try this code
                int Value = int.Parse(txtDatasend.Text);
                byte[] buffer = new byte[4];
                buffer[0] = (byte)(Value >> 24);
                buffer[1] = (byte)(Value >> 16);
                buffer[2] = (byte)(Value >> 8);
                buffer[3] = (byte)(Value >> 0);
                serialPort1.Write(buffer, 0, 4);
    
    i set a breakpoint and see the buffer is 0 ,1, 87, 192 when i give the value 88000
    but servo isn't action too
    how can i solve this problem?
    thanks

    propeller code
    CON
      _xinfreq=5_000_000            
      _clkmode=xtal1+pll16x                 
      
    VAR
      long position             
      byte p1[32]                                 
      long Stack[5]
                         
    OBJ
    pst : "FullDuplexSerialPlus" ' Serial communication object  
    PUB Demo
        pst.Start(31, 30, 0, 115200)
        p1 := Pst.rx << 24
        p1 |= Pst.rx << 16
        p1 |= Pst.rx << 8
        p1 |= Pst.rx
     
         
        cognew(MoveMotor(7),@Stack)
        repeat
          position:=p1                                                                          
          waitcnt(clkfreq+cnt)
    
    
                                                                                                                               
    PUB MoveMotor(Pin) | LowTime,period                  
      dira[Pin]~~                           '
      ctra[30..26]:=100                                                
      ctra[5..0]:=Pin                                                             
      frqa:=1                                             
      LowTime:=2*clkfreq/100                  
      period:=cnt                           
      repeat
        phsa:=-p1                     
        period:=period+p1+LowTime     
        waitcnt(period)
    
  • Mike GMike G Posts: 2,702
    edited 2012-10-22 22:21
    Give this a shoot. The Win form blinks LED/PIN 16 ? number of times.

    C# Code
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO.Ports;
    using System.Configuration;
    
    namespace SerialForm
    {
        public partial class Form1 : Form
        {
            private SerialPort sp;
            string port = "COM11";
            int baud = 115200;
    
    
            public Form1()
            {
                InitializeComponent();
                sp = new SerialPort(port, baud);
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                int num = 0;
                if(!int.TryParse(this.textBox1.Text, out num))
                    MessageBox.Show(@"Please enter a number!");
    
                sp.Open();
    
                string msg = string.Format("{0}\r", this.textBox1.Text);
                sp.Write(msg);
    
                sp.Close();
    
            }
        }
    }
    

    Spin Source
    CON
      _clkmode = xtal1 + pll16x     
      _xinfreq = 5_000_000
    
      LED = 16
    
    OBJ
      pst           : "Parallax Serial Terminal"
    
     
    PUB Main | int
    
      pst.Start(115_200)
      pause(500)
    
      repeat
        int := pst.DecIn
        repeat int*2
          Toggle(LED)
          
    
    PUB Toggle(pin)
      dira[pin]~~
        !outa[pin]
        waitcnt(80_000_000/4 + cnt)
    
    
      
    PRI pause(Duration)  
      waitcnt(((clkfreq / 1_000 * Duration - 3932) #> 381) + cnt)
      return
    
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-23 01:14
    thanks for your example Mike my servo is action
    but i have a new problem
    in first time i send 88000 to propeller and servo go clockwise position
    now i want servo to go counterclockwise position so i send 152000 to propeller
    but servo still go clockwise position
    how can i improve in the propeller code
    and if i want to use two servo i use two hScrollBar to send the value
    how can propeller Identification which value is servo1 and servo2
    i want to do just like previous theme
    http://forums.parallax.com/showthread.php?96973-VB-Express-to-Stamp-Template&highlight=Twin+Servo+Control
    #8
    thanks
  • Mike GMike G Posts: 2,702
    edited 2012-10-23 07:36
    ggg558877 wrote:
    in first time i send 88000 to propeller and servo go clockwise position
    now i want servo to go counterclockwise position so i send 152000 to propeller
    but servo still go clockwise position
    how can i improve in the propeller code
    I'm not sure. You'll have to debug your code. You might consider using servo32 in the OBEX as opposed to rolling your own.
    ggg558877 wrote:
    and if i want to use two servo i use two hScrollBar to send the value
    how can propeller Identification which value is servo1 and servo2
    Along with the servo position value, send the servo ID. You'll have to think about this and come up with a standard protocol so the Propeller and PC can decipher the data sent on the serial port.

    Here's an idea:
    ![ID][Value][$0D]
  • Mike GMike G Posts: 2,702
    edited 2012-10-23 14:09
    The attached C# and Propeller code should get you well on your way. The Zip contains 3 C# projects that can be used as templates.

    The ServoSlider project goes with the ReceivePacket.spin. Sorry, it does not move a servo. It only blinks LEDs according to the track bar position. I'll leave the servo stuff up to you.

    The SerialForm is the same project as posted on #12 and it goes with the spin code posted in the same post.

    Have fun
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-23 18:57
    thanks Mike it useful to me
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-23 20:58
    Hi, Mike
    I have a problem
    now i use ServoSlider project to change the LED blink speed
    and if value not change the LED keep this speed blinking
    if value change LED blinking on the new speed
    so i add this code
    if(id == 1)
          repeat   until  serial.rxcheck == "!"
            dira[LED1]~~
            !outa[LED1]
            waitcnt(80_000_000/4*value + cnt)
          serial.str(string("ID1 : Value "))
          serial.Dec(value)
    
    i try it
    sometime it success but sometime it have problem
    sometime i change the value LED keep bright or not bright
    can anyone give me some suggest?
  • Mike GMike G Posts: 2,702
    edited 2012-10-23 21:37
    First, you must understand what we're doing. The C# program is sending the Propeller a command. The command is made up of a start byte, an ID, length, payload, return.

    The payload is in little endian which means the least significant byte is sent first.
    ! $01 $04 $01 $00 $00 $00 $0D
    

    The spin code is simply disassembling the packet. First, the spin code looks for a "!". The next byte is the ID followed by the length of the payload, and ending with an $0D.

    This code block disassembles the command.
      repeat
        value := 0
        repeat until serial.rxcheck == "!"
        id := serial.Rx
        len := serial.Rx
        repeat i from 0 to len-1
          value |= serial.Rx << (i * 8)
    
        'The command should end with an $0D
        if(serial.Rx <> CR)
          next 
    

    Here's one way to change the blink rate. Add an parameter to the Toggle method and fix the number of times the LED blinks. The default program was setup to blink an LED 1 to 10 times depending on the trackbar position.
        if(id == 1)
          repeat 10
            Toggle(LED1, value)
          serial.str(string("ID1 : Value "))
          serial.Dec(value)
            
        if(id == 2)
          repeat 10
            Toggle(LED2, value)
          serial.str(string("ID2 : Value "))
          serial.Dec(value)
    
    
    PUB Toggle(pin, value)
      dira[pin]~~
        !outa[pin]
        waitcnt(80_000_000/(4 * value)  + cnt)
    
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-23 22:52
    Hi,Mike
    i think i have already understand what you say
    in your propeler code you blink an LED 1 to 10 times
    but now i want it blink in the same rate until the new command receive
    and it will blink in the new rate
    so i change
    repeat 10
    
    to
    repeat until serial.rxcheck == "!"
    
    is it not right?
  • Mike GMike G Posts: 2,702
    edited 2012-10-24 06:15
    but now i want it blink in the same rate until the new command receive
    and it will blink in the new rate
    How about two continuous processes. One process for each LED.


    This is a sample of the source. The entire source can be found in post 15
    PUB Main | id, len, value, i
      serial.start(31, 30, 0, 115200)
    
      'Initial blink rate
      rate[0] := 1
      rate[1] := 1
    
      'Start Toggle processes
      cognew(Toggle1, @stack1)
      cognew(Toggle2, @stack2)
    
      'Get the packet parameters
      repeat
        value := 0
        repeat until serial.rxcheck == "!"
        id := serial.Rx
        len := serial.Rx
        repeat i from 0 to len-1
          value |= serial.Rx << (i * 8)
    
        'The command should end with an $0D
        if(serial.Rx <> CR)
          next 
          
      
        if(id == 1)
          rate[id-1] := value 
          serial.str(string("ID1 : Value "))
          serial.Dec(value)
            
        if(id == 2)
          rate[id-1] := value
          serial.str(string("ID2 : Value "))
          serial.Dec(value)
    
    
    PUB Toggle1
      dira[LED1]~~
      repeat
        !outa[LED1]
        waitcnt(80_000_000/(4 * rate[0])  + cnt)
    
    PUB Toggle2
      dira[LED2]~~
      repeat
        !outa[LED2]
        waitcnt(80_000_000/(4 * rate[1])  + cnt)
    

    This type of information is also available in the Propeller Education Kit. From the Propeller tool click Help -> select Propeller Education kit.
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-24 22:33
    thanks Mike it's a good idea
    use this method my servo problem also can be solve
    but it have to use 2 cog to control 1 servo
    one to produce PWM ,one to control the servo's position
    if i just want use 1 cog to control servo
    do you have any suggest?
    thanks
  • Mike GMike G Posts: 2,702
    edited 2012-10-25 06:43
    but it have to use 2 cog to control 1 servo
    one to produce PWM ,one to control the servo's position
    if i just want use 1 cog to control servo
    Correct, one cog handles serial communication while another sends continuous PWM. The Servo32 object in the OBEX can control up to 32 servos. Counters are also an option.
  • JasonDorieJasonDorie Posts: 1,930
    edited 2012-10-25 14:33
    If you want to use one cog to control the servo, it'll have to run a loop that never blocks. You can use the pst.rxCheck function to find out if there is a character waiting or not, and if not, perform a servo loop. It would look something like this:
    repeat
      if( pst.rxCheck >= 0 )
        # recieve characters and process the commands
    
      SetServoPinHigh( ServoPin )
      Waitcnt( cnt + ServoHighTime )
      SetServoPinLow( ServoPin )
      Waitcnt( cnt + ServoLowTime )
    
      Waitcnt( cnt + ServoFrameTime )  # 20 milliseconds
    
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-29 08:07
    thanks for your suggest Mike and Jason
    i have a new problem
    i get the sensor data and now i want the value length is same
    for example
    100=100 , 10=010 , 1=001
    term.tx(1)
      if active & $8000                             
        term.str(string("Yaw = "))
        term.dec(yaw)
        term.str(string("   "))                    
      term.tx(13)
      if active & $4000 
        term.str(string("Pitch = "))
        term.dec(pitch)
        term.str(string("   "))
      term.tx(13)
      if active & $2000
        term.str(string("Roll = "))
        term.dec(roll)
        term.str(string("   "))
      term.tx(13)
    
    how can i change my code?
    and is there some easier example for propeller tx and C# serialport.read?
    thanks
  • Mike GMike G Posts: 2,702
    edited 2012-10-29 09:37
    thanks for your suggest Mike and Jason
    i have a new problem
    i get the sensor data and now i want the value length is same
    for example
    100=100 , 10=010 , 1=001
    That's called padding.
    CON
        _clkmode = xtal1 + pll16x
        _xinfreq = 5_000_000
     
    OBJ
      term : "Parallax Serial Terminal"
      
    PUB Main | num
      term.Start(115200)
      waitcnt(1_000_000 + cnt)
      
      num := 1
      term.str(string("Yaw = "))
      if(num < 10)
        term.char("0")
      if(num < 100)
        term.char("0")  
      term.dec(num)
      term.str(string("   "))
    
    
      num := 10
      term.str(string("Pitch = "))
      if(num < 10)
        term.char("0")
      if(num < 100)
        term.char("0")  
      term.dec(num)
      term.str(string("   "))
    
    
      num := 100
      term.str(string("Roll = "))
      if(num < 10)
        term.char("0")
      if(num < 100)
        term.char("0")  
      term.dec(num)
      term.str(string("   "))  
    
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-29 09:59
    thanks Mike
    now i want to send a command to C# to read the data value
    and the command just like !yaw|pitch|roll0D

      ser.tx("!")                
      ser.tx(yaw)        
      ser.tx("|")        
      ser.tx(pitch)           
      ser.tx("|")           
      ser.tx(roll)         
      ser.tx($0D)  
    
    or
      ser.str(string("!"))
      ser.dec(yaw)
      ser.str(string("|"))
      ser.dec(pitch)
      ser.str(string("|"))
      ser.dec(roll)                    
      ser.tx($0D)  
    
    is that right?
  • Mike GMike G Posts: 2,702
    edited 2012-10-29 10:42
    is that right?

    I do not know. Do you still require ASCII encoded zero padded 3 digit numbers? If so, then your example is NOT correct. Plus it appears that we're going from PST to FDS???
    CON
        _clkmode = xtal1 + pll16x
        _xinfreq = 5_000_000
     
    OBJ
      term : "Parallax Serial Terminal"
      
    PUB Main | num, yaw, pitch, roll
      term.Start(115200)
      waitcnt(1_000_000 + cnt)
    
      yaw := 1
      pitch := 10
      roll := 100
      
      num := yaw
      term.char("!")
      if(num < 10)
        term.char("0")
      if(num < 100)
        term.char("0")  
      term.dec(num)
    
      num := pitch
      term.char("|")
      if(num < 10)
        term.char("0")
      if(num < 100)
        term.char("0")  
      term.dec(num)
    
      num := roll
      term.char("|") 
      if(num < 10)
        term.char("0")
      if(num < 100)
        term.char("0")  
      term.dec(num)
      term.char($0D)
    
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-29 10:50
    Mike G wrote: »
    Plus it appears that we're going from PST to FDS???

    sorry what's the FDS mean?
  • Mike GMike G Posts: 2,702
    edited 2012-10-29 10:59
    The Full Duplex Serial object.
  • ggg558877ggg558877 Posts: 40
    edited 2012-10-29 11:18
    do you have a better way to assemble a command?

    thanks
  • Mike GMike G Posts: 2,702
    edited 2012-10-29 12:24
    do you have a better way to assemble a command?

    thanks

    Your requirements are not clear and change from post to post.

    If the requirement is to send pitch, roll, and yaw and the values do not exceed 0XFFFF (65,535) then I would send the following packet.

    ! [command] [low byte] [high byte] [CR]

    Where command is a number that represents pitch, roll, or yaw.

    pitch = 1
    roll = 2
    yaw = 3

    IMO, this packet format makes framing the packets on the PC side a little easier. However, it might not be the best method. You need to solidify the project requirements.
Sign In or Register to comment.