Using FullDuplexSerial to receive data via USB
ZachS
Posts: 28
Hi everyone,
I'm trying to write a program for the P1 that will allow the P1 to receive serial data via the USB port from a python program being run on the connected computer. The purpose is to broaden the functionality of automated testing that is typically done with a python program using pyserial. So I'm essentially trying to get the P1 to act like a bit whacker/banger. I'm currently using FullDuplexSerial but am having some trouble with it.
The code I'm using is below. I'll keep researching/experimenting, but if anyone has suggestions, I'd appreciate it.
Thanks,
Zach
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 RST = 15 'OLED pins DC = 16 CS = 17 CLK_oled = 18 DIN = 19 clk_enc = 28 'Encoder pins dt = 29 btn = 11 LED0 = 3 'pins LED1 = 4 LED2 = 5 LED3 = 6 LED4 = 7 LED5 = 8 LED6 = 9 LED7 = 10 Rx = 31 'Serial pins Tx = 30 LE = 2 'latch pin CLK_FREQ = (_clkmode >> 6) * _xinfreq MS_001 = CLK_FREQ / 1_000 'USB is on COM3 OBJ serial : "FullDuplexSerial" VAR long Data long DataX PUB Main serial.Start(Rx, Tx, %0000, 9600) repeat Data := serial.Rx ifnot DataX == Data outa[LED0] := (Data & %00000001) outa[LED1] := (Data & %00000010) >> 1 outa[LED2] := (Data & %00000100) >> 2 outa[LED3] := (Data & %00001000) >> 3 outa[LED4] := (Data & %00010000) >> 4 outa[LED5] := (Data & %00100000) >> 5 outa[LED6] := (Data & %01000000) >> 6 outa[LED7] := (Data & %10000000) >> 7 DataX := Data
Comments
The problem is not with FDS. I used FDS on a Propeller board that was communicating with the PC via PySerial for a TV commercial several years ago. It worked fine.
Zach,
Grabbing raw data seems simple at first, But due to the litany of problems I have encountered over the years and different systems, I always use a simple protocol that avoids bytes that various systems and serial implementations can choke on.
It goes like this:
Command to prop:
:FF
Where the colon lets my propeller program know there is real data in the string, Then the data in hex. It can be any length, as you seem to be using single bytes, I used two hex chars for 1 byte. Then followed by 13, (Return) so you can receive it like a string (Which it is...) Then convert the hex to a raw byte.
I use a similar protocol for data in the other direction as well..
Python can easily convert the data to/from hex, and I ripped off the hex converter from Parallax Serial Terminal for the propeller end.
This has the advantage that if you use a serial terminal (Parallax Serial Terminal perhaps) to debug, it is easy to see what is happening.
@JonnyMac ,
Thanks. My suspicion was that it was more likely an issue on my end (likely oversimplifying as @R Bagget is suggesting) as opposed to FullDuplexSerial. The python program I'm using I know works using a Bit Whacker from sparkfun. So I'm trying to use that same program to send that information (in this case binary 9) to the prop instead of the Bit Whacker and have the prop light up the LEDs that would correspond to that binary 9. Then the next step would be to tie those lines going to the LEDs to lines going to an RF component to drive its state. In this case, I'm loading the Spin program to EEPROM and then running the python program in the command prompt. The python program gets about as far as checking to make sure the com port is open ( the same com port that the prop is using) which it recognizes as being open, but then the python program seems to get stuck on the the section that configures the serial pins as outputs. I'm not sure if at this point there is some conflict between my python code and spin code that is holding things up. Any thoughts?
@R Baggett,
Thank you for that tip. That's also a good idea to take a look at how Parallax Serial Terminal handles that information. Could you send me an example so I can see what you're talking about in Spin?
Thank you both,
Zach
You need to set the LED pins to output first. This id done with the DIRA[] array.
If the LEDs are contiguous like in your case, you can just write the whole byte to the pin group, no need to check the bits separatly:
Andy
Good morning @Ariba ,
Thank you for pointing that out. I realized later that afternoon that there were a few small things like that I was missing. I fixed those but am still not getting the data coming over the serial port. My current code is posted below. I don't think it's an issue with my spin code. In using RxCheck from FDS, it's throwing a -1 and lighting the appropriate LED's to signal that there is no data coming through. So I'm now thinking that there may be an issue with my python code. The python code that I'm using to try and transfer the serial data works well with the JSB Bit Whacker (DEV-00762 from SparkFun), but I understand that they're using different chips that likely have different properties. I've tried a few other python code combinations to successfully transfer the data, but with no luck. I know this may not be kosher, but does anyone have a python code example that successfully transfers data over the serial port to the propeller?
Thanks,
Zach
Hi everyone,
I figured out what the issue was.
Thank you for all of the help!
Zach
You should probably share the solution so that others can learn from it.
Morning everyone,
Below is the code that ended up working for me to turn the P1 into a bit whacker that is sent the necessary data by a python program using the USB serial com port. The code is very much adapted from the parser code used in the program prop_serial_slave_010.spin, which is used in chapter 10 of "Programming and Customizing the Multicore Propeller Microcontroller" book from Parallax (highly recommended for anyone that wants a thorough introduction into spin and the P1 chip). It took me some time to fully understand and appreciate what the parser program was doing, but once I did, I was able to adapt it into the program so that the spin program could properly receive and parse the string being sent by the python program for the data within the string. Once parsed, each character (separated by a comma/space) is assigned a token value. Then a specific character can be taken out of the received string using its assigned token value (which is a string). To then use the program as a bit whacker, that token needs to be converted to a decimal value (done using the StrToDec(stringptr) method) and then "separated out" so that the binary representation of the decimal value in question is outputted using the eight LED's and attached wires that go to the mythical connected part to change its state.
Best,
Zach
I do have a question about the sharing of the serial com port.
My steps for running the above program are: load the program into EEPROM, start the python program in Windows command prompt, and then increment the python program forward. When the python program gets to its ser.open() function though it causes a restart event for the P1. I'm pretty sure that this is related to FDS, but does anyone know of a way around that restart event?
Thanks,
Zach
well - old problem. That is the way P1 handles programming.
Opening/closing a port in windows toggles DTR and resets the prop.
Putting something into a USB port on the computer re-enumerates the USB devices and toggles DTR and resets the Prop.
Even sending serial data from the P1 to the USB chip without having anything connected to the USB chip fires up the USB chip and resets the Prop.
The only solution I know of is to physically cut the trace between the USB chip and the propeller reset and put a jumper there to enable/disable reset on the P1.
Sadly
Mike
This all sounds incredibly complicated. On the P2, from the PC, I think you can just write a forth command and the P2 Taqoz interpreter will respond to it. And Taqoz can write to the terminal, and presumably Python can read it as a string.
Of course I have not yet done this, I am sure it will be more difficult than I expect. The devil is in the details.
Chris
It has nothing to do with taqoz or python. It is just the way programming the propeller is done.
Most of Parallax p1 or p2 boards have build in USB chips hardwired to the reset of the propellers and will reset when windows opens or closes a serial port.
It is by design. The only exception currently is the EDGE board, it does not have build in USB and you can use a prop plug with a small 3 pin header in between leaving the connection to reset disconnected.
Else it will hit you.
Mike
Thank you for the comments on the USB port/chip and reset relationship. I'll keep that in mind for the future.
Zach
The easiest (but not ideal) solution is to put a pull-up resistor on the Prop's TX pin. That will keep the USB chip powered parasitically whenever the Prop is powered, thus avoiding the resets when the program raises the TX pin.
-Phil
WOW.
And I foolishly thought that if the board has a usb plug on it, just plug in and go.
Thank you guys.
Chris
From the Eval Board Rev C Document:
I think that means that I can connect with a usb cable to the upper right of the eval board, and it will not reboot every time. Is that correct?
yes.
And on Rev C you can also use the small adapter board and the WiFi module when that switch is off.
Mike