Main Site Documentation

Cerbuino Net receive data from rs232.serialport and send to Uart


#1

Hi all.

Brand new to netmf and gadgeteer (and posting to forums).

Have a cerbuino net, and rs232 module.

I can receive data from the PC via the rs232 port, but have no idea about how to then send data from the uart pins on the headers of the mainboard.

Any help would be much appriciated.

The application is recieving a msg from a PC, then sending it on to an old school electronic tag (Dallas Semiconductor DS1201).

Thanks


#2

welcome to community.

http://media.digikey.com/pdf/Data%20Sheets/Dallas%20Semiconductor%20PDFs/DS1201.pdf

I looked for code samples and could not find any. not a popular device.

looks like you are going to have to develop a driver for the device.


#3

yes, welcome Reuben !

I’d always want to break this into two discrete “proof of concepts” - can I accept RS232 data and interpret it (if you need to interpret it, that is - seems you have proven that); and then how do I interface to the DS1201 device to give it data. Then the easy bit happens, you tie the two together to put the data/instruction etc from the RS232 serial line onto the tag.

As Mike says, really the first thing you will need to do is take a detailed look at the datasheet for the tag and figure out how to use it from scratch. If you break this down, it looks like a very similar approach to the onewire protocol, but I don’t think you will be able to use that to drive the chip. I’d approach this first as a bit-bang (set the data bit, toggle the clk line, set the next data bit, repeat…) and see if you can read/write successfully from the device. If you can, and this works fast enough for you, then I’d move forward with that - if not there are some complex solutions (RLP) but I wouldn’t go there unless it’s critical…

I’m sure there’s a spectrum that affects how robust you need to make this - are you doing this as a home project, a semi-serious side project, a work project, or as a commercial product ? If you can tell us where along the spectrum you need to target might also make a difference on how to approach this :slight_smile:


#4

Thanks Brett and Mike for the quick replies and wise advice.

So currently these tags are read and written to via an Atmel tinyAVR chip. It is using the bit-bang method and I have the C source code.

I was hoping to learn what it was doing by rewriting the code in vb.net and was hoping to use UART (which is apparently easier) to talk to it but it seems maybe I should go back to trying to bit bash it.

It needs to be quite robust as it will be a work project (work for a utility, won’t go down too well if I start breaking things).

I will try to transpose the C code over to vb.net (not very familiar with bitwise operations so I’ll see how I go.

Will report back when I get somewhere.

Please keep sending the advice though.


#5

Quick update and questions:

So I went down the path of bit-bashing to read/write to the Tag. I was writing it in VB.NET and found that bit shifting was not working in VB.NET, annoying, but good because it made me learn C#.

I am using the IO60P16 for the input/output and finally got all the code written (the messages being sent are DNP messages so I had CRC-16 DNP checks along the way) and got to testing and found that it read/writes really slowly.
I timed it at about 5ms for a read/write of a pin. With 128bytes to read/write, that time adds up real fast.

So I have decided to try and get it working off the pins on the mainboard.
Problem, I am struggling to get it to work.
I keep getting a Microsoft.SPOT.Hardware exception error.

So, using a cerbuino Net, can anyone get me starting on defining the pins on the mainboard and writing and reading to them.

This is what I have so far.:


    public partial class Program
    {
        //Not working----
        Cpu.Pin pwr_pin = GHI.Hardware.FEZCerb.Pin.PB11; //D0

        Cpu.Pin rst_pin = GHI.Hardware.FEZCerb.Pin.PB10; //D1

        Cpu.Pin clk_pin = GHI.Hardware.FEZCerb.Pin.PB12; //D2

        Cpu.Pin dat_pin = GHI.Hardware.FEZCerb.Pin.PC14; //D3

        OutputPort pwr;

        OutputPort clk;

        OutputPort rst;
        //----


        /* Working---
        IO60P16.OutputPort pwr;

        IO60P16.OutputPort clk;

        IO60P16.OutputPort rst;
        */

        void ProgramStarted()
        {
            Debug.Print("Program Started");
            //Not Working
            pwr = new OutputPort(pwr_pin, false);

            clk = new OutputPort(clk_pin, false);

            rst = new OutputPort(rst_pin, true);
            
            /* Working
            pwr = new IO60P16.OutputPort(io60p16 , IO60P16.IOPin.Port0_Pin0, false);

            clk = new IO60P16.OutputPort(io60p16, IO60P16.IOPin.Port0_Pin1, false);

            rst = new IO60P16.OutputPort(io60p16, IO60P16.IOPin.Port0_Pin2, true);
            */
            
            //dat_pin set to port1_pin3
            
            rs232.Initialize();

            multicolorLed.TurnGreen();

            rs232.serialPort.DataReceived += new GT.Interfaces.Serial.DataReceivedEventHandler(Port_DataReceived);
            
        }


#6

bit banging will always be slow - totally expected to see that behaviour. It’s about proving a communication pattern that works for your chip.

What exception are you seeing, and when ? Are you seeing it at run-time or compile time ? The code looks right but I haven’t tried it on hardware for you - will try to do that later when I get time and have a Cerb close by.


#7

Sorry, didn’t give many specifics.

The code compiles fine, it is when the serial recieves data and tries to process incoming data.

The data recieved code is:


        void Port_DataReceived(GT.Interfaces.Serial sender, System.IO.Ports.SerialData data)
        {
            Thread.Sleep(500);
            byte[] readData = new byte[rs232.serialPort.BytesToRead];
            rs232.serialPort.Read(readData, 0, readData.Length);
            multicolorLed2.TurnBlue();
            if (Check_DNP_CRC(readData) & readData[0] == (5) & readData[1] == 100) //check DNP CRC and if DNP starts with 0x05 0X64
            {
                Debug.Print("DNP msg found, correct");
                source_addr = (ushort)readData[7];
                source_addr <<= 8;
                source_addr += (ushort)readData[6];
                dest_addr = (ushort)readData[5];
                dest_addr <<= 8;
                dest_addr += (ushort)readData[4];
                if (My_Addr == dest_addr)
                {
                    multicolorLed2.BlinkOnce(new GT.Color(0, 0xff, 0));
                    if (readData[2] == 0x36 && Check_for_SICM_Str(readData)) //Command to Read tag
                    {
                        //turn tag power on
                        pwr.Write(true);
                        Thread.Sleep(20);
                        byte[] newdata = new byte[213];
                        newdata = readTag();
                        Thread.Sleep(20);
                        pwr.Write(false);
                        //bool check = Check_DNP_CRC(newdata);
                        rs232.serialPort.Write(newdata);
                    }
                    else if (readData[2] == 0xB6 && Check_for_SICM_Str(readData)) //Write tag
                    {
                        //code to write to TAG
                    }
                }
                else
                {
                    Debug.Print("DNP msg found, Incorrect");
                    multicolorLed2.TurnRed();
                    rs232.serialPort.Write(readData);
                }
            }
        }

the debug output is:

Program Started
DNP msg found, correct
A first chance exception of type ‘System.ArgumentException’ occurred in Microsoft.SPOT.Hardware.dll
Error invoking method “Tag_Burn.Program” (check arguments to Program.BeginInvoke are correct)

I have tried putting in Try Catch statements in to find the problem but it doesn’t help.

Thanks for your help


#8

Where exactly does the exception happen ?
Your problem, should you wish to call it that, is in mishandling the datareceived event.

First up, you have a sleep(500) and I know why you’ve done it, but you’re using the wrong method. The datareceived event is meant to be a flag to tell you that there’s data for you, that you then need to retrieve. You should retrieve it, push it into your own managed queue/buffer, and get out of the event as quickly as possible. Think of it like an interrupt handler; do as little in the handler as is possible, and figure out what your data means outside the handler.

Today your code assumes the whole data is received in one block - although that can’t be guaranteed (it can be enhanced by the sleep which should wait around for the data to arrive - but more data than expected could come through as well !). If you remove the business logic from the handler layer, and just process the queue you build outside the hander, you’ll get better reliability in cases where data does come sporadically.

There are some circular buffer and queue implementations around the place here that are good starting points too.


#9

Awsome. Thanks Brett.

Will change the code to use a queue and just add the items to the queue and get out.

Thanks for the quick reply.


#10

I have changed my code to handle the rs232 data received better, but I am still getting the exception error.

BUT, I have found out why now…

So when using the IO60P16, I would define the dat_pin as such:



I would then write (bit-bash) my data, and then I would dispose of the object.


```cs] out_data_pin.Dispose(); [/code


This was so that I could reuse that Port0_Pin3 for input.


```cs] IO60P16.InputPort in_data_pin = new IO60P16.InputPort(io60p16, IO60P16.IOPin.Port0_Pin3, IO60P16.ResistorMode.ResistivePullUp); [/code


If I didn't dispose of it, I would get an exception error saying that the Pin is already reserved.

I believe I am getting the same issue now with using the same Cpu.Pin for both output and input.

Declared:

```cs] Cpu.Pin dat_pin = GHI.Hardware.FEZCerb.Pin.PC14; //D3 [/code


Instance of Output

```cs
 
OutputPort out_dat = new OutputPort(dat_pin, false); 
//Write Data
out_dat.Dispose();
//New instance of Input
InputPort in_dat = new InputPort(dat_pin, true, Port.ResistorMode.PullUp); //falls over here
//Read Data
in_dat.Dispose();

Is there some other way to reuse this pin to read?

What am I doing wrong? Is it possible?


#11

@ Reuben - Try looking into TristatePort. It allows you to switch between reading and writing on one pin without disposing and recreating objects.


#12

@ John - Done! Worked! Thanks.