arduino serial communication

With this code.

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX
int mybyte;

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
mySerial.begin(2400);

}
void loop() {
// put your main code here, to run repeatedly:

if (mySerial.available() > 0) {
mybyte= mySerial.read();// read


if(mybyte<0x10){
Serial.print("0");

}
Serial.print(mybyte,HEX); //  hex 

//Will print the two nibbles of a byte.
if(mybyte >= 0xE8){
//Serial.print('\n');
Serial.println(" ");

}

//if(mybyte=0x1b){Serial.println("ac");} 

//if(mybyte=0x17){Serial.println("dc");}     


}

}

1B273D4F5D617F8297A0B0C0D4E8
1B273D4F5D617F8297A0B0C0D4E8
1B273D4F5D617F8297A0B0C0D4E8
1B273D4F5D617F819FA0B0C0D4E8
1B273D4F5D617F859BA0B0C0D4E8
1B273D4F5D617F859BA0B0C0D4E8
1B273D4F5D617F819FA0B0C0D4E8
1B273D4F5D617F839EA0B0C0D4E8
1B273D4F5D617F879EA0B0C0D4E8
1B273D4F5D617F879EA0B0C0D4E8
1B273D4F5D617F8297A0B0C0D4E8
1B273D4F5D617F819FA0B0C0D4E8
1B273D4F5D617F859BA0B0C0D4E8
1B273D4F5D617F8095A0B0C0D4E8
1B273D4855677E839FA0B0C0D4E8

I got this result.

‘1B273D4855677E839FA0B0C0D4E8’
means ‘ac 0.156 V’

So, I have to modify it according to it’s own protocol.

To do that.

I want to save that number each nibble just like ‘1b, 27, 3d,… e8’ to variable individually.
What command do I have to use?

Help me please.

I got this result.

What. a blank square ?

If that was an attempt to post the error message or Serial monitor by taking a screenshot then you would be better off copying and pasting it into code tags here.

UKHeliBob:
What. a blank square ?

If that was an attempt to post the error message or Serial monitor by taking a screenshot then you would be better off copying and pasting it into code tags here.

I’m sorry.

I Modified it.

kimjohn: I want to save that number each nibble just like '1b, 27, 3d,..... e8' to variable individually. What command do I have to use?

If I understand the problem correctly there is no single command but it should not be difficult.

You can convert the two halves of a byte into two bytes like this

byte topNibble = (dataByte & 0b11110000) >> 4;
byte lowNibble = dataByte & 0b00001111);

...R

Robin2: If I understand the problem correctly there is no single command but it should not be difficult.

You can convert the two halves of a byte into two bytes like this

byte topNibble = (dataByte & 0b11110000) >> 4;
byte lowNibble = dataByte & 0b00001111);

...R

Thank you so much. I'll try it.

Why do you want to save nibbles? Why not just store bytes in an array?

Are your message fixed length? Or do 0x1B and 0x8E have special meanings (something in the line of start and stop)?

I know you have this in your code

//if(mybyte=0x1b){Serial.println("ac");}

//if(mybyte=0x27){Serial.println("dc");}

You state that 0x1B indicates AC and 0x27 indicates DC. Which 0x1B; which 0x27?

PS Please post code using code tags. See how Robin did it (you even quoted hist post).

sterretje: Why do you want to save nibbles? Why not just store bytes in an array?

Are your message fixed length? Or do 0x1B and 0x8E have special meanings (something in the line of start and stop)?

I know you have this in your code

//if(mybyte=0x1b){Serial.println("ac");}

//if(mybyte=0x27){Serial.println("dc");}




You state that 0x1B indicates AC and 0x27 indicates DC. Which 0x1B; which 0x27?

PS
Please post code using code tags. See how Robin did it (you even quoted hist post).

Data type is

1b 27 3d 4f 5d 62 77 83 9f A0 B0 C0 D4 E8

Each nibble's first numbers are 1,2,3,4,5,6,7,8,9,a,b,c,d,e It is always same.

1x,2x,3x,4x,5x,6x,7x,8x,9x,ax,bx,cx,dx,e8

'e8' is not changed.

'0x1B' is 'ac'

'0x17' is 'dc'

each nibble is each segment's 4 led on/ off protocol.

So.

'1b 27 3d 4f 5d 62 77 83 9f A0 B0 C0 D4 E8 '

is 'ac 0.156v'

I want to see 'ac 0.156v' on my arduino monitor ultimately not '1b 27 3d 4f 5d 62 77 83 9f A0 B0 C0 D4 E8 '.

OK, this is the datasheet?

Are you sure that 0x1B indicates AC and 0x17 indicates AC and not the other way around.

7 = 0111
B = 1011

If the bit is low, the indicator is on so 0x7 would indicate AC and 0xB would indicate DC.

These are just my thoughts.

kimjohn: So.

'1b 27 3d 4f 5d 62 77 83 9f A0 B0 C0 D4 E8 '

is 'ac 0.156v'

A first analysis of the table on page 14 shows that that is not the case for the numeric part. If I did not make mistakes, these are the representations of the digits

        x561 4372

0       .111 1101     0x7D
1       .000 0101     0x05
2       .101 1011     0x5B
3       .001 1111     0x1F
4       .010 0111     0x27
5       .011 1110     0x3E
6       .111 1110     0x7E
7       .001 0101     0x15
8       .111 1111     0x7F
9       .011 1111     0x3F

x561 is the first part for a digit, 4372 the second part of the digit; x represents the sign or a decimal dot and the dot in that column indicates that it's a don't care for the number representation.

extracting from your sequence '1b 27 3d 4f 5d 62 77 83 9f A0 B0 C0 D4 E8' 2*7* 3*d* 4*f* 5*d* 6*2* 7*7* 8*3* 9*f* -> 7d fd 27 3f -> 0.049

Maybe that's because it's AC.

From the data in the opening post, only the last one seems to be 'close' to your 0.156

1B 27 3D 4F 5D 61 7F 82 97 A0B0C0D4E8   0.030
1B 27 3D 4F 5D 61 7F 82 97 A0B0C0D4E8   0.030
1B 27 3D 4F 5D 61 7F 82 97 A0B0C0D4E8   0.030
1B 27 3D 4F 5D 61 7F 81 9F A0B0C0D4E8   0.033
1B 27 3D 4F 5D 61 7F 85 9B A0B0C0D4E8   0.032
1B 27 3D 4F 5D 61 7F 85 9B A0B0C0D4E8       2
1B 27 3D 4F 5D 61 7F 81 9F A0B0C0D4E8       3
1B 27 3D 4F 5D 61 7F 83 9E A0B0C0D4E8       5
1B 27 3D 4F 5D 61 7F 87 9E A0B0C0D4E8       6
1B 27 3D 4F 5D 61 7F 87 9E A0B0C0D4E8       6
1B 27 3D 4F 5D 61 7F 82 97 A0B0C0D4E8       4
1B 27 3D 4F 5D 61 7F 81 9F A0B0C0D4E8       3
1B 27 3D 4F 5D 61 7F 85 9B A0B0C0D4E8       2
1B 27 3D 4F 5D 61 7F 80 95 A0B0C0D4E8       1
1B 27 3D 48 55 67 7E 83 9F A0B0C0D4E8   0.169

PS I've tried to invert the data in the table but the result did not seem to make sense in relation to the data that your presented.

Thank you. I agree.

Data is always changing. I annoyed Analyze exectly. So picked random value in my multi-tester.^^

I noticed an error in the first 3 values that I presented in the last code block in reply #8; 0.030 should be 0.034.

This could be a function to read your device data. Data is stored in an array. It has two checks. The first one is that it checks the first received byte so it can sync to it. The second one is that it checks if the 14th received byte is 0x8E. You can add additional checks if needed.

/*
  read data from device
  returns:
    pointer to data if complete packet received, else NULL
*/
byte *readDevice()
{
  // buffer
  static byte rxBuffer[14];
  // index in buffer where to store next byte
  static byte index = 0;

  if (mySerial.available())
  {
    rxBuffer[index] = mySerial.read();
    // sync on first byte; must be 1Xh
    if (index == 0 && (rxBuffer[index] & 0xF0) != 0x10)
    {
      Serial.print("no sync: ");
      return NULL;
    }
    // last byte must be 0xE8
    if ((index == sizeof(rxBuffer) - 1) && rxBuffer[index] != 0xE8)
    {
      Serial.print("no EOM: ");
      index = 0;
      return NULL;
    }
    index++;
  }

  // if packet complete
  if (index >= sizeof(rxBuffer))
  {
    // reset index for next read of packet
    index = 0;
    // indicate we have data
    return rxBuffer;
  }
  else
  {
    // indocate data not complete
    return NULL;
  }
}

You can use this in loop() as shown below

void loop()
{
  // read data packet
  byte *dataPacket = readDevice();

  // if packet complete
  if (dataPacket != NULL)
  {
    // print the data
    printData(dataPacket);
  }
}

Next you can implement printData to print the received data in a format that your want. Below the framework.

/*
  print received data
  in:
    pointer to received data
*/
void printData(byte *dataPacket)
{
  // data for a digit will be collected in this variable
  byte digitData = 0;

  // index in received data (dataPacket)
  byte index = 0;

  // print SEG1
  printSeg1(dataPacket[index]);
  index++;

  // print the digits (SEG2..SEG9)
  for (index; index < 9; index++)
  {
    if (index % 2 == 1)
    {
      // first part of digit
      digitData = dataPacket[index] << 4;
    }
    else
    {
      // second part of digit
      digitData |= dataPacket[index] & 0x0F;

      // digit is now complete

      // print sign or decidmal dot
      if ((digitData & 0x80) == 0x80)
      {
        if (index == 2)
        {
          // first digit, sign
          Serial.print("-");
        }
        else
        {
          // other digits, decimal dot
          Serial.print(".");
        }
      }

      // print the digit
      printDigit(digitData);
    }
  }
  Serial.println();

  // print SEG10
  printSeg10(dataPacket[index]);
  index++;
  // print SEG11
  // print SEG12
  // print SEG13
  // print SEG14
}

It basically prints the segments in sequence. The interesting part (for your original question) is the combining of the data for a digit in the section ‘print the digits (SEG2…SEG9)’.

Next you need to implement the functions printSeg1, printDigit and so on.

/*
  print digit data as number
  in:
    data for a digit
 */
void printDigit(byte digitData)
{
  // strip sign or decimal dot
  // and display
  switch (digitData & 0x7F)
  {
    case 0x7D:
      Serial.print(0);
      break;
    case 0x05:
      Serial.print(1);
      break;
    case 0x5B:
      Serial.print(2);
      break;
    case 0x1F:
      Serial.print(3);
      break;
    case 0x27:
      Serial.print(4);
      break;
    case 0x3E:
      Serial.print(5);
      break;
    case 0x7E:
      Serial.print(6);
      break;
    case 0x15:
      Serial.print(7);
      break;
    case 0x7F:
      Serial.print(8);
      break;
    case 0x3F:
      Serial.print(9);
      break;
    default:
      // you can add an error message here
      break;
  }
}

After stripping bit that represents the sign or decimal dot, this simply uses a switch/case with the values from the table in reply #8 to convert to a number.

For the first segment, you can implement something in this line

/*
  print the segment 1 data; format: |RS232|AUTO|DC|AC|
  in:
    segment 1 data
*/
void printSeg1(byte data)
{
  data &= 0x0F;
  //Serial.print("SEG1 = 0x"); Serial.println(data, HEX);
  if ((data & 0x01) != 0x01)
  {
    Serial.print("|RS232");
  }
  if ((data & 0x02) != 0x02)
  {
    Serial.print("|AUTO");
  }
  if ((data & 0x04) != 0x04)
  {
    Serial.print("|DC");
  }
  if ((data & 0x08) != 0x08)
  {
    Serial.print("|AC");
  }
  Serial.println("|");
}

void printSeg10(byte data)
{
}

I leave the other segments to you; an empty printSeg10 is added so the code will compile.

The above was tested with serial data on the hardware serial port (Serial instead of mySerial) and RealTerm to send data in binary format.

I’ve also tested the printData with your sample data from the opening post

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); // RX, TX

byte examples[][14] =
{
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x82, 0x97, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x82, 0x97, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x82, 0x97, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x81, 0x9F, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x85, 0x9B, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x85, 0x9B, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x81, 0x9F, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x83, 0x9E, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x87, 0x9E, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x87, 0x9E, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x82, 0x97, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x81, 0x9F, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x85, 0x9B, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x4F, 0x5D, 0x61, 0x7F, 0x80, 0x95, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
  {0x1B, 0x27, 0x3D, 0x48, 0x55, 0x67, 0x7E, 0x83, 0x9F, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},

  {0x1b, 0x27, 0x3d, 0x4f, 0x5d, 0x62, 0x77, 0x83, 0x9f, 0xA0, 0xB0, 0xC0, 0xD4, 0xE8},
};


void setup()
{

  Serial.begin(57600);

  // print the example data
  for (int cnt = 0; cnt < sizeof(examples) / sizeof(examples[0]); cnt++)
  {
    printData(examples[cnt]);
  }
}

I think you have sufficient ammunition to modify it to your needs.

  1. read the data
  2. print digits
  3. print sign and decimal dot
  4. extract individual bits for the other segments

Note:
AC/DC (and RS232 and AUTO) based on my comment in reply #7.

Your code is outstaning!
I’m so impressed.

I tried your code. It’s excellent!

I’m so appriciate you.

I wish your entire life lucky! happy! and God bless you!

Glad that you're happy. I hope you understand the code.

I am trying to understand.

But it's so hard.^^

Someday I'll get it!

kimjohn: I am trying to understand.

But it's so hard.^^

Someday I'll got it!

Ask about what you don't understand; I will try to explain.

sterretje: Ask about what you don't understand; I will try to explain.

I don't know how to ask.

I think I have to learn more about 'C' language's 'pointer' , 'array' and so on.

Your code will be a good textbook for doing it.

I'll read it again, again and again till I understand it.