Main Site Documentation

Fez Spider e RS485


#1

I connect my rs485 to Rs485 other two doors enter into communication.
I read the data with the function SENDER and can give commands, but how can I display the data read on my display T43?


#2

To Display anything on your display you could use a GUI system.
NETMF comes with WPF.
GHI offers Glide, which is included in the latest SDK.
There are other GUI system like Clix from Skewworks you could use.
You can find several tutorials and documentation verywhere around here and on NETMF codeplex site.
With any of these GUI systems you create a window, add a textbox and display text in it.

If you only want to output text like in an simple console window you should open CodeShare here and search for the word “console”.
The top 3 answers should do what is needed for this.


#3

For many applications a GUI framework like WPF or Glide is overkill. A simple graphic display can be done using basic Bitmap operations.

This document should help you get started: https://www.ghielectronics.com/docs/34/displays


#4

Thank you, solved in part.

For byte works like this:

this.rs485.Port.Write((byte)d);

LCD.DrawText("La distanza è = cm " + sender.ReadByte(), MyFont, Colors.Red, 100, 100);

I do not know how to go about the STRINGS.

this.rs485.Port.WriteLine(“ciao”);

??


#5

If you want to convert a string from and to byte array you can use
Encoding.UTF8

not sure if this is located in System or System.Text namespace.


#6

Questo programma si azione solo al primo rilascio del Button e non hai successivi, qualcuno sa qual’è il problema?

this.rs485.Port.DataReceived += (sender, data) =>

        {
            this.rs485.Port.Open();
            if (sender.ReadByte() == (byte)'X')
            {
                LCD.Clear();
                LCD.DrawText("ciao" + sender.BaudRate, MyFont, Colors.Red, 100, 40);
                LCD.DrawText("ciao" + sender.ReadByte(), MyFont, Colors.Red, 100, 60);

                LCD.DrawText("ciao" + sender.ReadByte(), MyFont, Colors.Red, 100, 80);
                LCD.DrawText("La distanza è = cm " + this.rs485.Port.ReadByte(), MyFont, Colors.Red, 100, 100);

                LCD.Flush();
                this.led_Strip.TurnAllLedsOn();
                Thread.Sleep(1000);
                
                this.rs485.Port.Write((byte)'T');
      
            }

            if (sender.ReadByte() == (byte)'Y')
            {
                LCD.Clear();
                LCD.DrawText("ciao" + sender.BaudRate, MyFont, Colors.Red, 100, 40);
                LCD.DrawText("La Lumminosita' e' = % " + sender.ReadByte(), MyFont, Colors.Red, 100, 100);
                LCD.Flush();
                this.led_Strip.TurnAllLedsOn();
                Thread.Sleep(1000);
               
            }
            
            this.led_Strip.TurnAllLedsOff();
            this.rs485.Port.Close();
            
        };

        this.button.ButtonReleased += (sender, e) =>
        {

            this.rs485.Port.Write((byte)'Q');
        };
        
	}
    
}

#7

according to a translator this is your question:
“This program takes action only on the first release of the Button and you don’t, does anyone know what is the problem?”

in your DataReceived event handler you 1st open the port.
But to receive data the port already needs to be open, right?
At the end of the event handler you close the port.
I assume that the call to open does nothing because it’s already open.
But when you call close, the port is closed, and by this no DataReceived event is fired anymore.


#8

… in other words, you should open the port at the start of your app and close it at the end (or never, since microcontroller apps never really end, do they).


#9

Fixed connection issues.
Now I will try to create a function of the Modbus slave.
eg 3 Read Holding Registers.
I know that first I have to create the crc algorithm
Does anyone know how I can do
thanks


#10

You can find a ready to use Modbus implementation for NETMF here:
https://www.ghielectronics.com/community/codeshare/entry/880


#11

Have you ever used this library on Fez Spider 1.0 or fez cerderus?
You have some examples?


#12

Spider 1 (EMX) should not be a problem, with Cerberus I have no experience.
When you go to the codeshare entry, you can switch to the usage example just above the code/browse window.
It contains 4 snippets for RTU/TCP master/slave.
I have no short and complete sample at hand.


#13

I would like to read on my FEZ SPIDER1.0 the will of his temperature sensor giving the command from my SCADA.

how to do ?

How to use libraries on FEZ SPIDER1.0 ?

The library that I would use is:
https://www.ghielectronics.com/community/codeshare/entry/880 RTU


#14
  1. Download the project from codeshare.
  2. Open the sln file in visual studio.
  3. Make a release build
  4. Open your project in Visual Studio
  5. Add a reference to the Modbus.Netmf.dll (can be found in bin/release folder of Modbus lib after build)
  6. Initialize the Modbus lib (as Modbus RTU Master I assume)
using Osre.Modbus;
using Osre.Modbus.Interface;

...

// RTU master
// Replace PortName, BaudRate, Parity, DataBits and StopBits with your values
// like new SerialPort("COM1", 9600, Serial.Parity.Even, 8, 1);
var serialPort = new SerialPort(PortName, BaudRate, Parity, DataBits, StopBits);
serialPort.Open();
var rtuInterface = new ModbusRtuInterface(serialPort);
var master = new ModbusMaster(rtuInterface);

// call Modbus function code methods as needed
master.WriteSingleCoil(1, 0, true); // throws ModbusException on error


#15

I want to use my FEZ SPIDER1.0 as SLAVE.

Giving commands from a SCADA interface.

Using a serial RS485 and read the value of LightSensor


#16

Well then:

replace code by this:


using Osre.Modbus;
using Osre.Modbus.Interface;
...

// provide access to MyModbusDevice via RTU
// Replace PortName, BaudRate, Parity, DataBits and StopBits with your values
// like new SerialPort("COM1", 9600, Serial.Parity.Even, 8, 1);
var serialPort = new SerialPort(PortName, BaudRate, Parity, DataBits, StopBits);
serialPort.Open();
var rtuInterface = new ModbusRtuInterface(serialPort);
// the 2nd parameter (1) is the Modbus address of your slave. Choose anything between 1 and 247. Must be unique on the bus.
var device = new MyModbusDevice(rtuInterface, 1);
device.Start();
// ...
// call device.Stop() if you want to stop your device from responding to RS485
device.Stop();

...

// implement slave device like this
// add any function code overload you want to provide by your slave
public class MyModbusDevice : ModbusDevice
{
    public MyModbusDevice(byte deviceAddress, object syncObject = null)
       : base(deviceAddress, syncObject)
    { }

    public MyModbusDevice(IModbusInterface intf, byte deviceAddress, object syncObject = null)
       : base(intf, deviceAddress, syncObject)
    { }

    protected override string OnGetDeviceIdentification(ModbusObjectId objectId)
    {
       switch (objectId)
       {
          case ModbusObjectId.VendorName:
             return "MeManufacturer";
          case ModbusObjectId.ProductCode:
             return "1";
          case ModbusObjectId.MajorMinorRevision:
             return "1.0";
          case ModbusObjectId.VendorUrl:
             return "http://www.MeManufacturer.org";
          case ModbusObjectId.ProductName:
             return "MyModbusDevice";
          case ModbusObjectId.ModelName:
             return "1";
          case ModbusObjectId.UserApplicationName:
             return "MyModbusApplication";
       }
       return null;
    }

    protected override ModbusConformityLevel GetConformityLevel()
    {
       return ModbusConformityLevel.Regular;
    }

    protected override ModbusErrorCode OnWriteSingleCoil(bool isBroadcast, ushort address, bool value)
    {
       if (false) // check address here
       {
          return ModbusErrorCode.IllegalDataAddress;
       }
       
       // set coil value here
       
       return ModbusErrorCode.NoError;
    }

    protected override ModbusErrorCode OnReadCoils(bool isBroadcast, ushort startAddress, ushort coilCount, byte[] coils)
    {
       if (false) // check coil count here
       {
          return ModbusErrorCode.IllegalDataValue;
       }
       if (false) // check address here
       {
          return ModbusErrorCode.IllegalDataAddress;
       }

       // write coil values into parameter coils here
       
       return ModbusErrorCode.NoError;
    }
    
    // override any On<ModusFunction> methods here
}


#17

step where the information of the sensor to return to my master?

this.rs485.Port.Write((byte)lightSensor.ReadLightSensorPercentage());


#18

With the framework provided, you don’t need to send anything on your own.
For sensor data I would implement the OnReadHoldingRegisters of ModbusDevice.
There you can return multiple registers with 16 bit unsigned (ushort) each.

Lets say you define that the 1st input register (with 16 bit) holds your sensor value.
The length of the parameter registers tells you how many registers the master wants to read starting at startAddress

 registers)
{
   if (startAddress == 0 && registers.Length >= 1)
   {
      // read input value from sensor here and convert it to 16 bit unsigned
      ushort value = ...
      registers[0] = value;
      return ModbusErrorCode.NoError;
   }
   return ModbusErrorCode.IllegalDataAddress;
}

You master would then need to send a read holding registers message, with address = 0 and number of registers = 1.

All the communication and error handling is done by the library for you


#19

The library also maintains two different sensors on the same slave?

example:

address 0 sensorA

address 1 sensorB

how to implement it on the slave.


#20

You can manage as many sensors as you want.
What you need to do is map the values to the Modbus registers.
Modbus is only a protocol to access single bit values and 16 bit registers on a slave.
It also separates between input only bits and registers and read/write bits and registers.
The protocol (and by this my library) only provides read and write methods to those.

If you have sensors which provides a 16 bit number each, you can map each sensor to a single register address. If you have for example 32 bit values, you have to split them in two registers.

You should check out the first chapters of the Modbus documentation, on how slaves can organize their values:
http://modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf