Posted on Leave a comment

Arduino: Transmit 10-bit ADC Reading Through Serial

So the standard Serial.write() or Serial.print in Arduino land is 8-bit All this really means is we need to send one byte ( bits) at a time. If we try to send 10 bits, then bad things happen.

On top of that, it’s better to setup a secret word for start and another one for end. This is the same thing that naked couples do when they get out the power tools. They need safe words. Maybe we all do. Anyhow, by telling our receiver not to bother receiving until it hears the start word and not to finish until it hears the end word, we can be much more confident that the data we are receiving is legit.

A good chunk of this code was taken from various sources from this article. https://forum.arduino.cc/t/serial-input-basics-updated/382007/3

Sending

// Uses ATmega4808  (Thunder Magnum dev board)
#include <Arduino.h>

#define LEDPIN PIN_PA7
#define LEDPIN2 PIN_PA6

int sensorValue;
int newsensorValue;

#define MONITOR_SPEED 115200
void setup()
{
  // put your setup code here, to run once:
  pinMode(LEDPIN, OUTPUT);

  // Setup serial with 2nd ucontroller
  Serial.begin(MONITOR_SPEED); // PA0 is tx and PA1 is rx

  // Setup serial with computer
  Serial1.begin(MONITOR_SPEED); // PC0 is tx.   PC1 is rx.
}

void loop()
{

  // 10 bit ADC read
  newsensorValue = analogRead(PIN_PD0);

  // throw away the lowest 8 bytes to send just the biggest 2 bits
  int Bigbyte = (newsensorValue >> 8);

  // AND 0b1111111 with ADC read to keep only the lowest 8 bits
  int Littlebyte = newsensorValue & 0xFF;

  // talk to computer com port
  Serial1.print("sending: ");

  // combine back together and talk to computer ( sanity check )
  Serial1.println((Bigbyte << 8) + Littlebyte);

  byte startMarker = 0x3C;
  byte endMarker = 0x3E;

  // Talk to 2nd microcontroller
  Serial.write(startMarker);
  Serial.write(Bigbyte);
  Serial.write(Littlebyte);
  Serial.write(endMarker);

  delay(1000);
}

Receive

// Uses ATmega4808  (Thunder Magnum dev board)
#include <Arduino.h>

#define LEDPIN PIN_PA7
#define LEDPIN2 PIN_PA6

void showNewData();
void recvBytesWithStartEndMarkers();

const byte numBytes = 32;
byte receivedBytes[numBytes];
byte numReceived = 0;

boolean newData = false;

#define MONITOR_SPEED 115200
void setup()
{
  // put your setup code here, to run once:
  pinMode(LEDPIN, OUTPUT);

  Serial.begin(MONITOR_SPEED);  // PA0 is tx and PA1 is rx
  Serial1.begin(MONITOR_SPEED); // PC0 is tx.   PC1 is rx.


  digitalWriteFast(LEDPIN, LOW);
  delay(1000);
}

void loop()
{
  recvBytesWithStartEndMarkers();
  showNewData();
}

void recvBytesWithStartEndMarkers()
{
  static boolean recvInProgress = false;
  static byte ndx = 0;
  byte startMarker = 0x3C;
  byte endMarker = 0x3E;
  byte rb;

  while (Serial.available() > 0 && newData == false)
  {
    rb = Serial.read();
 
    if (recvInProgress == true)
    {
      if (rb != endMarker)
      {
        receivedBytes[ndx] = rb;
        ndx++;
        if (ndx >= numBytes)
        {
          ndx = numBytes - 1;
        }
      }
      else
      {
        receivedBytes[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        numReceived = ndx; // save the number for use when printing
        ndx = 0;
        newData = true;
      }
    }

    else if (rb == startMarker)
    {
      recvInProgress = true;
    }
  }
}

void showNewData()
{
  if (newData == true)
  {
    Serial1.println("Received: ");
 
    int receivedandformatted = (receivedBytes[0] << 8) + receivedBytes[1];
    Serial1.println(receivedandformatted);

    Serial1.println();
    newData = false;
  }