Manchester decoding 200hz

ive a project where we need to read out 2 different electrical waves, each one with a different header. The first one is set by me (10bit signal) and is followed by a 7bit manchester encoded signal. The second one depends on how many coordinates i need to read out, the coordinates are always in pairs of 5 bits, 10 bits total, it should be able to read out a maximum of 20 coordinate pairs. My problem is that i cant get the timing right and i dont know why. Here is the code i came up with, I also added some text to further explain the code.

The transmitter works fine, ive tested it with an oscilloscope, so i dont know why the code isnt working how it should be.

const int signalPin = 2;
const unsigned long halfBitMicros = 5000;  // 5ms per half-bit

uint8_t frequency = 0;
uint8_t coordCount = 0;
uint8_t coords[20][2];  // Maximum 20 coordinate pairs

// Sample a single half-bit at the midpoint
int readHalfBitStable() {
  unsigned long t0 = micros();
  while (micros() - t0 < halfBitMicros / 2);  // Wait until halfway through half-bit
  return digitalRead(signalPin);
}

// Read and decode a single Manchester bit (two half-bits)
int readManchesterBit() {
  int first = readHalfBitStable();

  unsigned long t1 = micros();
  while (micros() - t1 < halfBitMicros);  // Wait to next half-bit boundary
  int second = readHalfBitStable();

  if (first == 0 && second == 1) return 0;
  if (first == 1 && second == 0) return 1;
  return -1;  // Invalid Manchester encoding
}

// Detect fixed 10-bit sync pattern: 1010101010
bool detectSync1() {
  int expected[] = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0};
  for (int i = 0; i < 10; i++) {
    int bit = readHalfBitStable();
    if (bit != expected[i]) return false;
    unsigned long t = micros();
    while (micros() - t < halfBitMicros);  // Wait until next half-bit
  }
  return true;
}

// Read raw binary bits (non-Manchester, just 1 bit every 5ms)
uint16_t readRawBits(uint8_t bitCount) {
  uint16_t result = 0;
  for (int i = 0; i < bitCount; i++) {
    int bit = readHalfBitStable();
    result = (result << 1) | (bit & 0x01);
    unsigned long t = micros();
    while (micros() - t < halfBitMicros);  // Wait next bit
  }
  return result;
}

// Read N Manchester-encoded bits
uint16_t readManchesterBits(uint8_t bitCount) {
  uint16_t value = 0;
  for (int i = 0; i < bitCount; i++) {
    int bit = readManchesterBit();
    if (bit == -1) return 0xFFFF;  // Error
    value = (value << 1) | bit;
  }
  return value;
}

void setup() {
  pinMode(signalPin, INPUT);
  Serial.begin(9600);
  delay(1000);  // Wait for serial setup
}

void loop() {
  // Wait for first sync pattern
  while (!detectSync1());

  // Decode 7-bit frequency (14 half-bits = 7 Manchester bits)
  uint16_t freqBits = readManchesterBits(7);
  if (freqBits == 0xFFFF) return;  // Bad Manchester sequence
  frequency = freqBits;

  // Decode second sync header: 10 raw bits (number of coordinate pairs)
  coordCount = readRawBits(10);
  if (coordCount > 20) coordCount = 20;  // Safety cap

  // Read coordinate data
  for (int i = 0; i < coordCount; i++) {
    uint8_t x = readManchesterBits(5);
    uint8_t y = readManchesterBits(5);
    coords[i][0] = x;
    coords[i][1] = y;
  }

  // Debug output after full frame
  Serial.print("Frequency: ");
  Serial.println(frequency);
  Serial.print("Coordinates: ");
  Serial.println(coordCount);
  for (int i = 0; i < coordCount; i++) {
    Serial.print("X: ");
    Serial.print(coords[i][0]);
    Serial.print(" Y: ");
    Serial.println(coords[i][1]);
  }

  delay(500);  // Optional delay before next read
}

Pleas post both sketches transmitter and receiver. Say if the code you posted is in fact the exact receiver.

TIA

a7

Im getting the transmitted wave from a zybo, ive tested the timings a lot so im 100% sure the problem isnt bad timing at the transmitter. I dont have the code right nog but i could send it tomorrow, its all in verilog tho so idk if that would be relevant. But im very confident that the transmitter is working perfectly fine

Quick question - why are you using Manchester encoding?

If it wasn't a requirement you had no control over, what informed your decision to use it?

a7

I don't think you do it like this. Function detectSync1() contains a lot of blocking code. While it is the middle of checking if the 10 bit initial signature is present, the transmitter may start sending and that will simply get lost.

I think you should always be looking at each bit in the incoming data stream, that is transitions LOW to HIGH or HIGH to LOW, then trying to determine if that transition occurred at a midbit , which you are interested in, or at a boundary which you discard. Then start looking for patterns in it such as the start sequence.

which microcontroller are you using?

maybe worth considering a ESP32, e.g. have a look at post reading-a-pulse-train

Well the transmitter is quite a bit easier to write than the receiver.
Manchester is a protocol that allows a fair bit of drift in the clock, because it's self-clocking so to say. Also it allows for an undetermined polarity.
I would use an interrupt to detect a CHANGE in the pin state and measure the time in between. 200Hz (i am assuming this means 200bps) results in approximately 2.5ms per half-bit, so any interval over 3750us should result in a a double HIGH or LOW, and anything less should result in a single HIGH or LOW.
That will result in a bit flow that you can decode. the sync test would then look like
10011001100110011001

This actually means that you are receiving at 100bps, using Hz in Manchester encoding is a tad ambiguous,
But mainly i think you are setting the boundary way to close to the Half-bit length. You should test for anything being more than say 3500us and less than 7500us and for a double valley or hill, for more than 7500us, up to 12500us and if the change is outside of 3500us - 12500us then you should reject. You don't allow for the drift and aim for the exact to much.

Our professor said this would be one of the best methodes for accurate readings and inplementing fault recovery code

Ive seen some other people decoding manchester waves like this, ill try to inplement this. And each of the halfbits takes 5ms

im using an arduino nano

I had tinkered and created a project that used manchester coding a while back.
depending on your level of programming skill you may find it useful! :wink:

hope that helps....

what do you mean "is followed by"? isn't the entire data stream using Manchester encoding?

Manchester encoding combines the clock a data, there is a transition in the middle of each data bit.

but you can't sample at the same frequency, or in this case twice the frequency with the expectation that a transition occurs at the sample instant. you need to sample faster to detect a transition within your sampling period and resynchronize your sampling cycles with each transition

4x sampling is not unreasonable

well yeah, but its just a header so it doensnt need to be translated or anything, i just need to find the header first so the code can read the actual data that comes after the headers

is it better do use this, or to work with boundaries like Deva_Rishi said? Ive asked chatgpt and it says that both methods are fine but i dont kown if i should trust that haha

Have a look at DALI Which uses manchester encoding at 1200bps. What you don't do, and what you should do, is send a byte in a Serial format, with start & stop bits. That way, the first thing you receive is always a '1' (the start bit) and you will always receive full bytes. If you want to add a header, you can do this is part of a byte in fact your header already is). 1010101010, comes down to 8N1 01010101 = 64 + 16 + 4 + 1 = 85.

There probably is a DALI library available for arduino which you can slow down to suit your needs.

i assume you're asking is Manchester encoding can be intermeshed with other encoding schemes?

i don't know why you would do that if there's a clock with other encoding scheme.

natural intelligence or something artificial. True intelligence will try and work it out for it self first before asking the question.

:slight_smile:

At the rate you are taking, software synthesized serial at both ends would be very easy to code.

Ask your professor. I don't see Manchester encoding as offering anything that would be better at getting "accurate readings and inplementing fault recovery code".

That is all in your protocol design. As has been observed, your code really won't work at all. Woyncha just use an easier method?

As for "accurate readings and inplementing fault recovery code", see

HTH and say Hi to the professor for me.

a7