Showing posts with label RS485. Show all posts
Showing posts with label RS485. Show all posts

Sunday, June 1, 2014

Modification to RS485 Shield - Arduino Web Logger

Finally, we are using SD card.

In Ethernet Shield use Pin 4 as SD_CS.  If we just leave everything as it is, we are not going to be able to use them.

Originally:

  • Pin 3: RX
  • Pin 4: TX
  • Pin 2: DE
We are going to modify it so that it becomes:
  • Pin 3: RX
  • Pin 5: TX
  • Pin 2: DE

I'm going to cut RS-485 Shield.





In all previous codes I used Pin 4 as TX, and because I don't want to fix all the codes I soldered a wire onto the pin.  So now I can move TX to Pin 4 or Pin 5 depending on what I need.







Tuesday, May 27, 2014

ADAM - 4017 Arduino Gateway

ADAM-4017

The manual "ADAM-4000_manual_V20.pdf" can be downloaded from the following site.
http://support.advantech.com.tw/support/DownloadSRDetail_New.aspx?SR_ID=1%2BGE%2B715&Doc_Source=Download

Use INIT* as GND and set RS-485 Address as "00". Unlike ADAM-4050, settings need to be modified.

Configuration Command

%AANNTTCCFF(cr) ( refer to manual page 150 )
  • AA: "00" current RS-485 address.
  • NN: "02" new address for RS-485. You can set it to anything. I used "02" because I used "01" for ADAM-4050
  • TT: "08" input range. ( refer to manual page 152 ). ±10V, for now I used maximum.
  • CC: "06" 9600 bps ( refer to manual page 152 ).
  • FF: "00" ( refer to manual page 152 ).
    • <b7> 0: 60 Hz
    • <b6> 0: Checksum Disable
    • <b5 b4 b3 b2> 0000
    • <b1 b0> 10: ( refer to manual page 387 ).
      Receives the 12 bit AD read value in binary format.
      It becomes 3 byte HEX-ASCII.
      However, ADAM-4050 does not support this, thus ?01(cr) will be returned.
    • <b1 b0> 00: If you set it to 00, you receive voltage value within the input range.
      If the input range is equal to ±10V, it returns values between -10.000 - +10.000, which is very nice.

Analog Input

#AAN(cr) ( refer to manual page 161 )
  • AA: "00" RS-485 address
  • N: "0" channel 0 - 7. We are using 0.
Response
>HHH(cr)
  • HHH: It returns 3 byte HEX-ASCII. "000" - "FFF"
    ADAM-4050 does not support this.
OR

>+dd.ddd(cr)
  • +dd.ddd: The following 7 bytes value gets returned. -10.000 - +10.000. 




Friday, May 23, 2014

Arduino Code(2) - Web/Arduino/Adam

Let's make a very simple protocol to use for WebSocket.

For Digital Out:
     Turning on: "DOn=ON"
     Turning off: "DOn=OFF"
     n: channel number 0-7

For Digital In:
     If you send "DI" it returns "bbbbbbbb".
     'b' is each input channel. It either becomes '0' or '1'.


#include <SPI.h>
#include <Ethernet.h>
#include <WebSocket.h>
#include <SoftwareSerial.h>

byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0x25, 0xC4 };
byte ip[] = { 192, 168, 219, 16 };
WebSocket wsServer;

int DE485 = 2;
SoftwareSerial Soft485(3, 4);

char rx485Ln[8];
int rx485ix;
char bitMap[8];

void AdamReceiver(void);
void hexToBit(char hex, int p);

void setup() {
 Serial.begin(9600); // Arduino Sketch Serial Monitor

 Soft485.begin(9600);
 pinMode(DE485, OUTPUT);

 Ethernet.begin(mac, ip);
 wsServer.registerConnectCallback(&onConnect);
 wsServer.registerDataCallback(&onData);
 wsServer.registerDisconnectCallback(&onDisconnect);
 wsServer.begin();
 delay(100);

 rx485ix = -1;
}

void loop() {
 wsServer.listen();
 AdamReceiver();
}

void onConnect(WebSocket &socket) {
 Serial.println("onConnect called");
}

void onDisconnect(WebSocket &socket) {
 Serial.println("onDisconnect called");
}

void onData(WebSocket &socket, char* rxLn, byte rxSz) {
 // Digital Out
 // It is either "DOn=ON" or "DOn=OFF". n = "0" - "7"
 // It would really be nice if we can parse "DO", "=ON",
 // "=OFF"; however, we are not focusing on this.
 // In "DO" we are only checking for "O" and for "=ON" & 
 // "=OFF", we will only check for "N".
 if(rxLn[1] == 'O') {
  // RS-485 will be in TX mode when DE is high
  digitalWrite(DE485, HIGH);
  // We send to ADAM-4050 "#001n01"<cr> if ON or
  // "#001n00"<cr> if OFF.
  Soft485.write("#001");
  Soft485.write(rxLn[2]); // n = "0" - "7"
  Soft485.write('0');
  if(rxLn[5] == 'N')
   Soft485.write('1');
  else
   Soft485.write('0');
  Soft485.write(0x0D);
  digitalWrite(DE485, LOW); // When finished, DE must be low
 }

 // Digital In
 // We are only looking for "I" in "DI"
 else if(rxLn[1] == 'I') {
  digitalWrite(DE485, HIGH);
  Soft485.write("$006"); // We send "$AA6"<cr> to ADAM-4050
  Soft485.write(0x0D);
  digitalWrite(DE485, LOW);
 }
}

// ADAM-4050 sends "!ooii00"<cr> as reply.
// The message starts with "!" and ends in <cr>, and there are 6
// bytes in between. The input data are the "ii". For more 
// information look at ADAM - Web/Arduino/Adam posting.
void AdamReceiver(void) {
 char rxChr;

 if(Soft485.available()) {
  rxChar = Soft485.read();
  if(rxChr == '!')
   rx485ix = 0; // message starts with "!"
  else if(rx485ix >= 0) {
   if(rxChr == 0x0d) { // message ends with <cr>
    //!ooii00<cr> Between "!" and <cr> there needs to be
    // 6 bytes
    if(rx485ix == 6) {
     hexToBit(rx485Ln[2], 0);
     hexToBit(rx485Ln[3], 4);
     wsServer.send(bitMap, 8);
    }
    rx485ix = -1; // it needs to be sync to "!" again
   }
   else {
    rx485Ln[rx485ix++] = rxChr;
    if(rx485ix > 6)
     // it cannot be greater than 6 bytes.
     // Re-sync to "!".
     rx485ix = -1;
   }
  }
 }
}

// We send "bbbbbbbb" to WebSocket. b is equal to each input channel, and it becomes either '0' or '1'.
void hexToBit(char hex, int p) {
 int i;

 if(hex >= 'A')
  hex = hex - 0x41 + 10;
 else
  hex -= '0';
 hex ^= 0x0f;

 for(i = 0; i < 4; i++) {
  if(hex & 0x08)
   bitMap[p + i] = '1';
  else
   bitMap[p + i] = '0';
  hex <<= 1;
 }
}



The code can be downloaded from:
https://github.com/michelleseo/Arduino_Web/blob/master/WSAdam/WSAdam.ino





Thursday, May 22, 2014

Arduino Code(1) - Web/Arduino/Adam

The basic tutorial for WebSocket:
http://www.tutorialspoint.com/html5/html5_websocket.htm

The code that I used for WebSocket is from the following site:
http://jlectronique.org/WebsocketsEN.htm

Now back to the original TOPIC.

Code for Arduino WebSocket


include
#include <SPI.h>
#include <Ethernet.h>
#include <WebSocket.h> 

Ones that must be defined
/* Mac Address
  Each Ethernet Shield has different mac address. 
  Check your board.
*/
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0F, 0x25, 0xC4 };

/* IP Address
  Arduino becomes the server, and it needs fixed IP.
  It doesn't necessarily need global IP, it just needs fixed IP.
  Most LAN connections use DHCP, so use an Local IP address that 
  DHCP doesn't use.
  HOW?
     Open command promp and type ipconfig /all
     Check the IP Address for the current PC. 
     Keeping the same Subnet Mask, try pinging IP addresses.
     If you find the IP address that doesn't answer the ping,
     use that IP address.
     If someone around you gets pissed off because their internet 
     doesn't work, change the IP address quickly and quietly before
     he notices you.
*/
byte ip[] = { 192, 168, 100, 11 };

Create WebSocket Callback
/*
  There are 3 Callbacks in WebSocket.h.
  You should be able to guess what they are for just by looking at
  there names.

    typedef void DataCallback(WebSocket &socket, char* socketString, byte frameLength);
    typedef void Callback(WebSocket &socket);

    void registerDataCallback(DataCallback *callback);
      // Called when received Data
    void registerConnectCallback(Callback *callback);
      // when WebSocket is connected
    void registerDisconnectCallback(Callback *callback);
      // when WebSocket is disconnected
*/
WebSocket wsServer;
void onData(WebSocket &socket, char* socketString, byte frameLength) { }
void onConnect(WebSocket &socket) { }
void onDisconnect(WebSocket &socket) { }

Code inside setup()
void setup() {
 Ehternet.begin(mac, ip);
 wsServer.registerConnectCallback(&onConnect);
 wsServer.registerDataCallback(&onData);
 wsServer.registerDisconnectCallback(&onDisconnect);
 wsServer.bein();
 // Give Ethernet Shield some time to get ready.
 delay(100);
}

Code inside loop()
void loop() {
 wsServer.listen();

 if(wsServer.isConnected()) {
  wsServer.send("abc123", 6);
 }
}

/*
  listen() needs to be called continuously.
  If data is received onData() gets called.
  If you want to send data send(char *str, byte length);
*/

RS-485 Connection Code


include
#include <SoftwareSerial.h>

Ones that must be defined
SoftwareSerial Soft485(3, 4);
int DE485 = 2;

/*
  Pin 3: RX
  Pin 4: TX
  Pin 2: DE This was declared in 
      RS485 Shield - Web/Arduino/Adam posting.
*/

Code inside setup()
void setup() {
 Soft485.begin(9600);
 pinMode(DE485, OUTPUT);
}

/*
  ADAM-4050 is 9600 bps. (ADAM - Web/Arduino/Adam posting)
*/






Wednesday, May 21, 2014

RS485 Shield - Web/Arduino/Adam

I have purchased following RS-485 Shield.
https://www.tindie.com/products/Conceptinetics/rs485-rs422-shield-for-arduino/





RS-485 Shield






































There was no manual ( just like I expected :( ), and shockingly schematic was not included.
Furthermore I couldn't even find the information about the manufacturer.  I sent an email to the address on the PCB ( info@conceptinetics.com.hk ), and got the following:



RS-485 Schematic

This was unexpected.  Guess I should be thankful that they replied.





Anyways...

Although it is not shown on the schematic, there is a Jumper to allow the use of Soft Serial Port.  There are 3 Jumpers; however, Arduino Uno only has one Serial Port so we are going to use Soft Serial Port.

     EN
     TX-io
     RX-io    Set them for Jumper



Pin Settings:

  • Pin 3: RX
  • Pin 4: TX
  • Pin 2: DE


DE is only set to 'H' when transmitting, and at other times ( receiving ) DE is set to 'L'.  At other times Soft Serial is same as general serial, thus we don't have to care.

In Ethernet Shield, Pin 4 is used as SD_CS; however for now we are not using SD thus we don't have to worry about it.  If you really want to use SD, you have to move TX to somewhere around Pin 5 which involves cutting and soldering.  Very annoying...





Tuesday, May 20, 2014

UNO, Ethernet Shield - Web/Arduino/Adam

UNO

I used UNO, the most basic Arduino model.

The one I purchased is from the following Korean site, and it is not the original version.
http://www.nulsom.com/
You could purchase it from other sites ( a lot of them sell it ).
http://eleparts.co.kr/EPX7R9BJ
http://devicemart.co.kr/goods/view.php?seq=38296

This machine gives off a lot of heat ( enough heat to make me worry about the PCB ).

Arduino UNO from http://www.nulsom.com/





Ethernet Shield


This is an original, I purchased it from plughouse (Korean site).
http://www.plughouse.co.kr/shop/goods/Goods_view.php?G_code=102705472330

Ethernet Shield





UNO + Ethernet Shield + RS-485 Shield

Let's stack all 3.

Arduino UNO + Ethernet Shield + RS-485 Shield





Photo with ADAM!

Arduino UNO + Ethernet Shield + RS-485 Shield, Adam-4050, LED & Switches






Monday, May 19, 2014

ADAM - Web/Arduino/Adam

ADAM-4050

This is the most basic Digital Input / Output ADAM series module. ( also the cheapest* )


Download the manual "ADAM-4000_manual_V20.pdf" from the above link. 
( This manual is for the entire 4000 series modules. ADAM-4050 starts on page 74 )


ADAM has 8 Outputs and 7 Inputs.
I have attached 8 LED and 7 DIP Switches ( BEST for testing ). 

ADAM 4050 module w/ 8 LED & 7 DIP Switch
































Circuit?

Very simple. ( It's in manual pg.75 )
I set INIT* pin to GND because I didn't want to confuse 485 Address. This sets Address = 0, Speed = 9600 bps, and Checksum = disabled. ( manual pg.19 )

Circuit w/ Switch and LED











RS-485 Protocol

For ADAM-4050 command set refer to manual pg.130.
The ones that we actually use are:
  • Digital Data In (pg.241) that begins with '$' and
  • Digital Data Out (pg.243) that begins with '#'


The Confusing Question...

Is this protocol only using visible ASCII ( 0x20 - 0x7f )? or is Binary also being used?
Except for the line termination Cr ( 0x0d ), only Visible ASCII are used.

Digital Data Out

#AABB( data )( cr )
  except for ( cr ), #AABB( data ) is string
  • AA is address for 485
    AA = "00" because we have set INIT* as GND
  • BB is channel address
    If "00", it writes to all 8 channels at the same time.
    ( data ) ranges from "00" to "FF"
    lsb is DO 0, and msb is DO 7.
    ( eg. If you want to turn ON DO 7 and DO 5 and rest OFF, the ( data ) will be "A0" )

    If "10" - "17", it writes to each channel.
    "10" will turn ON DO 0, ... , "17" will turn ON DO 7
    In this case ( data ) is either "00" or "01".
It says as response we receive ">( cr )"; however we are not going to care about this for now.

Digital Data In

$AA6( cr )
  • AA is address for 485
  • 6 is Digital Data in Command
Response: !( dataOutput )( dataInput )00( cr )
  • ( dataOutput ) Loop back from output.
    2 character string. If we get "A0", it means that DO 7 and DO 5 is ON and rest are OFF.
  • ( dataInput )
    2 character string. This value is what we want.
  • "00"
    We don't know what this is for, so let's not worry about this.