Pages: [1]   Go Down
Author Topic: Combining bits and sending as hex  (Read 690 times)
0 Members and 1 Guest are viewing this topic.
N. Illinois
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to make my Mega 2560 send and receive data from a PLC.  PLC's code I know well, but not C so much. I have a bunch of bits in the plc that I need to write to.  It needs to be formatted so that each nibble of data represents 4 bits but gets send over in 2 byte chunks with the high byte first then the low byte.  The code below (written to send 6 bytes) works until I turn on that 4th bit and then it craps out because it sends an (0f) rather than a 3430 .  I have been staring at this for 2 days, and searching for the solution. I'm not saying its not here, if it is I just don't understand it. Any insight would be MUCH appreciated, I would rather figure it out on my own unfortunately time has run out.

The actual data format to send is 02|42|32303030|3031|3030|0D  = (The pipes are not needed just to make it easier to see)
This would send it STX|A|2000|01|00|CR  (A = Write Command |2000 = address to read| 01 # of Bytes| 00 = Value to write| Carriage return)
I attached 2 pics of the format as well.  

Code:
/*
 MATRIX KEYPAD CONVERTER
 
 
 ***************************************************************************************************
 
 Note:  
 The Inputs and Outputs are configured for a Custom Keypad with 40 LED's in a 5x8 matrix
 SET GOT to microcomputer driver 9600, N, 8, 1
 Must Jump Pins 4-6, 7-8 on the GOT serial side.
 Must use TTL to 232 Converter on Pins 2 & 3
 
 ****************************************************************************************************/


//general constants and variables

//variables for Writing Bits M0 - M47


String sendData = "";
String readData = "";
const char STX = 2;
char command[2] = "B"; // Write Virtual M Bits
char command2[2] = "A"; //Read Virtual M Bits
String stNo = "00";
String address = "2000"; //M0 of Virtual Device (Buttons)
String raddress = "2100"; // M100 of Virtual Device (LED's)
String count = "06"; // How many Bytes
byte n[] = {
  0,0,0,0,0,0,0,0,0,0,0,0};
char inChar;
char response[100] = "";
boolean m[50]; //Set up Bits for Keys
boolean LED[50]; //Set up Bits for LED's
int i = 0;

/***********************************************************************************************************************************************************************************
 * The setup routine runs on power cycle or when you press reset:
 *
 ***********************************************************************************************************************************************************************************/

void setup()
{
  // initialize serial communication at 9600 bits per second:
  Serial1.begin(9600);
  Serial.begin(9600);

  // Just set values for Testing
  m[0] = 1;
  m[1] = 1;
  m[2] = 1;
  m[3] = 0; //Ugh turn this bit on and get a Format Error

}

/*********************************************************************************************************************************************************************************
 * The loop routine runs over and over again forever:
 *
 **********************************************************************************************************************************************************************************/
void loop()
{
  for (i=0; i < 4; ++i){
    bitWrite(n[0],i, m[i]); //Move bits into Bytes
    bitWrite(n[1],i, m[i+4]);
    bitWrite(n[2],i, m[i+8]);
    bitWrite(n[3],i, m[i+12]);
    bitWrite(n[4],i, m[i+16]);
    bitWrite(n[5],i, m[i+20]);
    bitWrite(n[6],i, m[i+24]);
    bitWrite(n[7],i, m[i+28]);
    bitWrite(n[8],i, m[i+32]);
    bitWrite(n[9],i, m[i+36]);
    bitWrite(n[10],i, m[i+40]);
    bitWrite(n[11],i, m[i+44]);
  }
  SendKeysCommand(); //Write Keys to GOT


  delay(1000);

  ReadData();
  while ((Serial.available() > 0) && i <99) //read response data. Currently ignored
  {
    inChar = (char)Serial.read();
    response[i] = inChar;
    i += 1;
  }

  CommTest();

}
/*******************************************************************************************************************************************************************************
 * SUB ROUTINES
 ********************************************************************************************************************************************************************************/

void SendKeysCommand()  //send Key State to GOT through Serial 1
{
  sendData = (command) + (stNo) + (address) + (count);
  Serial1.write (STX);
  Serial1.print (sendData);
  Serial1.print (n[1]);  //Bytes must be swapped High Byte then Low Byte
  Serial1.print (n[0]);
  Serial1.print (n[3]);
  Serial1.print (n[2]);
  Serial1.print (n[5]);
  Serial1.print (n[4]);
  Serial1.print (n[7]);
  Serial1.print (n[6]);
  Serial1.print (n[9]);
  Serial1.print (n[8]);
  Serial1.print (n[11]);
  Serial1.println (n[10]);
  
}

void ReadData() //Read Data from GOT through Serial 1
{
  readData = (command2) + (stNo) + (raddress) + (count);
  Serial1.write (STX);
  Serial1.println (readData);
}

void CommTest()  //Send Data out Serial port to monitor
{
  Serial.print ("DATA SENT: ");
  sendData = (command) + (stNo) + (address) + (count);
  Serial.write (STX);
  Serial.print (sendData);
  Serial.print (n[1]);  //Bytes must be swapped High Byte then Low Byte
  Serial.print (n[0]);
  Serial.print (n[3]);
  Serial.print (n[2]);
  Serial.print (n[5]);
  Serial.print (n[4]);
  Serial.print (n[7]);
  Serial.print (n[6]);
  Serial.print (n[9]);
  Serial.print (n[8]);
  Serial.print (n[11]);
  Serial.println (n[10]);
 
  Serial.print ("Received: ");
  Serial.println (response);
}

The Actual Error
I get is on the Controller Side. It (PLC) tells me that the message is not properly formatted. The Mega happily goes along sending.


* format.jpg (18.82 KB, 455x113 - viewed 21 times.)

* format2.jpg (31.49 KB, 351x198 - viewed 20 times.)
« Last Edit: March 02, 2013, 10:23:31 am by bobert0670 » Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 625
Posts: 34112
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Read the sticky post at the top of the page on how to use the forum, modify that post and then we can talk.
Logged

N. Illinois
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OOPS thanks for the heads up.
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 625
Posts: 34112
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for responding positively.
I have had a look at the code and I am concerned about the variable i in the main loop. You seem to be using it for a loop and also as some sort of cumulative counter.
Also the code could do with a bit of simplification. I have simplified it and made the i in the for loop a local variable.
See what you think:-
Code:
/*
 MATRIX KEYPAD CONVERTER
 
 
 ***************************************************************************************************
 
 Note: 
 The Inputs and Outputs are configured for a Custom Keypad with 40 LED's in a 5x8 matrix
 SET GOT to microcomputer driver 9600, N, 8, 1
 Must Jump Pins 4-6, 7-8 on the GOT serial side.
 Must use TTL to 232 Converter on Pins 2 & 3
 
 ****************************************************************************************************/


//general constants and variables

//variables for Writing Bits M0 - M47


String sendData = "";
String readData = "";
const char STX = 2;
char command[2] = "B"; // Write Virtual M Bits
char command2[2] = "A"; //Read Virtual M Bits
String stNo = "00";
String address = "2000"; //M0 of Virtual Device (Buttons)
String raddress = "2100"; // M100 of Virtual Device (LED's)
String count = "06"; // How many Bytes
byte n[] = {
  0,0,0,0,0,0,0,0,0,0,0,0};
char inChar;
char response[100] = "";
boolean m[50]; //Set up Bits for Keys
boolean LED[50]; //Set up Bits for LED's
int i = 0;

/***********************************************************************************************************************************************************************************
 * The setup routine runs on power cycle or when you press reset:
 *
 ***********************************************************************************************************************************************************************************/

void setup()
{
  // initialize serial communication at 9600 bits per second:
  Serial1.begin(9600);
  Serial.begin(9600);

  // Just set values for Testing
  m[0] = 1;
  m[1] = 1;
  m[2] = 1;
  m[3] = 0; //Ugh turn this bit on and get a Format Error

}

/*********************************************************************************************************************************************************************************
 * The loop routine runs over and over again forever:
 *
 **********************************************************************************************************************************************************************************/
void loop()
{
  for (int i=0; i < 4; ++i){
      for(int j=0; j <12; j++){
        bitWrite(n[j],i, m[j*4]); //Move bits into Bytes
        }
  }
  SendKeysCommand(); //Write Keys to GOT


  delay(1000);

  ReadData();
  while ((Serial.available() > 0) && i <99) //read response data. Currently ignored
  {
    inChar = (char)Serial.read();
    response[i] = inChar;
    i += 1;
  }

  CommTest();

}
/*******************************************************************************************************************************************************************************
 * SUB ROUTINES
 ********************************************************************************************************************************************************************************/

void SendKeysCommand()  //send Key State to GOT through Serial 1
{
  sendData = (command) + (stNo) + (address) + (count);
  Serial1.write (STX);
  Serial1.print (sendData);
  for(int i=0; i<12; i+=2) {
  Serial1.print (n[i+1]);  //Bytes must be swapped High Byte then Low Byte
  Serial1.print (n[i]);
  }
  Serial1.print(char(13));
 
}

void ReadData() //Read Data from GOT through Serial 1
{
  readData = (command2) + (stNo) + (raddress) + (count);
  Serial1.write (STX);
  Serial1.println (readData);
}

void CommTest()  //Send Data out Serial port to monitor
{
  Serial.print ("DATA SENT: ");
  sendData = (command) + (stNo) + (address) + (count);
  Serial.write (STX);
  Serial.print (sendData);
 
    for(int i=0; i<12; i+=2) {
  Serial1.print (n[i+1]);  //Bytes must be swapped High Byte then Low Byte
  Serial1.print (n[i]);
  }
 
  Serial.print ("Received: ");
  Serial.println (response);
}
Logged

Phillipsburg, NJ
Offline Offline
Full Member
***
Karma: 6
Posts: 184
Author: Matrix Keypad Library
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I looked to see if you are properly forming your messages and it seems like you are.

One thing I can think of is that you are using Arduino 1.0.3.  I've had to deal with a lot of very strange problems when people compile the keypad library with that version.  Even if it successfully compiles the problems that is has seem to me like it is overwriting memory locations.

If you are using that version then I would try a different one.
Logged

N. Illinois
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grumpy,
Thanks for the simplification, I was going to do that once I figured out the problem, the old one thing at a time approach. As for the the way I was using the i since I was doing it the long way I was using it to set the correct bit (of the byte) and to select the correct M array value. I have tested your code and it is not working at all if ANY of the bits are high.  The string that gets developed looks like this B00200006 01 50 00 00 00 00 0 somewhere I am picking up an extra byte if I make any bits true with this code. Also the first 4 bits should only affect the values in the first 2 bytes so the extra byte is coming before it should read B00200006 15 00 00 00 00 00.
As well, if I put nay of the bits high it sends the same value so somewhere the bits are not being correctly written.


mstanley,
I tried both my old code and the sample provided by Grumpy and I get the same results.

I will keep plugging away at this. I am also going to download a different serial monitor that allows me to see the real string being sent rather than the conversion.
Logged

N. Illinois
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK SO I have stumbled upon something here.  here is the current operation
bit status 0,0,0,1  it sends 31
bit status 0,0,1,1  it sends 33
bit status 0,1,1,1  it sends 37
bit status 1,1,1,1  it sends 31 35
bit status 1,0,0,0  it sends 38

So its converting the Decimal value to hex therefore adding the extra when it is decimal 15.  I need it to convert the HEX value to, it all works out the same until all the bits are on, or the bits are non sequential 1,0,0,1 etc.
0,0,0,1  it should send 31(1)
0,0,1,1  it should send 33(3)
0,1,1,1  it should send 37(7)
1,1,1,1  it should send 46(f)
1,0,0,0  it should send 38(smiley-cool
1,0,0,1 = 39(9)
1,0,1,1 = 42(b)

Any Ideas?
Logged

Rome, Italy
Offline Offline
Sr. Member
****
Karma: 20
Posts: 442
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bit status 1,1,1,1  it sends 31 35

1,1,1,1  it should send 46(f)

[edit - I rewrote my initial comment leaving aside misleading questions]
Looking at the format, I get that 0,0,0,3 is 3, and 3 is ASCII code 33, so it sends 00 33.
Now 1,1,1,1 is 0x0f, and you expect it to send 46. But since 1,1,1,1 is also 15, I would expect it to require two half bytes, 31 35.

Are you sure that it should send 46?
« Last Edit: March 02, 2013, 08:10:39 pm by spatula » Logged

N. Illinois
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Spatula,

Yes I am sure.  If you look at the images on the original post it shows the format.  Each Ascii Character represents 4 bits. And I know our PLCs are are Hex biased so they are actually looking for the Hex value. we have specific commands in our PLC for just this sort of deal. Not sure how to do it in Arduino though.
[Modify] Also since 1111 1111 would be a decimal of -1, the actual characters it would need to send if FF or 46 46  i tested this by modifying the original code with this mod.
Code:
sendData = (command) + (stNo) + (address) + (count);
  Serial1.write (STX);
  Serial1.print (sendData);
  Serial1.print (n[1]), HEX;  //Bytes must be swapped High Byte then Low Byte
  Serial1.print ("F"); //Send F character in place of first nibble
  //Serial1.print (n[0]);
  Serial1.print (n[3]);
  Serial1.print (n[2]);
  Serial1.print (n[5]);
  Serial1.print (n[4]);
  Serial1.print (n[7]);
  Serial1.print (n[6]);
  Serial1.print (n[9]);
  Serial1.print (n[8]);
  Serial1.print (n[11]);
  Serial1.println (n[10]);
 
}

And the PLC received the data and was correctly setting the bits.   So now I just need to get the Arduino to Read the HEX Value rather than the Decimal value, when it send it out.
« Last Edit: March 02, 2013, 09:31:35 pm by bobert0670 » Logged

N. Illinois
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK Me being a dufus again.  I had the hex conversion in there but was missing the extra brackets.  So this now works.
Code:
void SendKeysCommand()  //send Key State to GOT through Serial 1
{
  sendData = (command) + (stNo) + (address) + (count);
  Serial1.write (STX);
  Serial1.print (sendData);
  Serial1.print ((n[1]), HEX);  //Bytes must be swapped High Byte then Low Byte
  Serial1.print ((n[0]), HEX);
  Serial1.print ((n[3]), HEX);
  Serial1.print ((n[2]), HEX);
  Serial1.print ((n[5]), HEX);
  Serial1.print ((n[4]), HEX);
  Serial1.print ((n[7]), HEX);
  Serial1.print ((n[6]), HEX);
  Serial1.print ((n[9]), HEX);
  Serial1.print ((n[8]), HEX);
  Serial1.print ((n[11]), HEX);
  Serial1.println ((n[10]), HEX);
 
}
Logged

N. Illinois
Offline Offline
Newbie
*
Karma: 0
Posts: 29
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you Spatula, MStanley, and Grumpy Mike. Sometimes it helps to have another person to talk things through with. I am going to try to figure out why your (Grumpy) code simplification did not work and use that now that I have figured out the correct format to send the data.  I need to implement the Keypad Matrix, and then an LED matrix to control the LED outputs now, I have done some testing and think I have it figured out, thanks to posts in this forum.  Thanks again for your help, I will continue to use this forum and try to help others as well.  Once complete I will post the code for others who may need something like this. BTW here is a link http://www.meau.com/functions/dms/getfile.asp?ID=060000000000000001000011905300000to the plc and GOT that I am communicating with, it is probably too expensive for most projects but you never know. My Actual setup will be Custom Keypad --> GOT --> PLC.  The GOT has dual ports allowing me to talk to both the Arduino and the PLC.
Logged

Pages: [1]   Go Up
Jump to: