Bytes become bits

While in one of my previous posts, I used a byte per LED, a better solution is to use a bit per LED. That could go 8 times faster… Speaking of performance: apparently there is a method of controlling pins that is about 30 times faster compared with the digitalWrite() function. Keep you posted. Find below the updated Arduino code.

/*
   Test reading 8 bytes input from serial port.

   Reads 8 bytes from the serial port to control a series of leds that represent annunciator status fields of the KA350i.
   The final implementation will use a MAX7219ENG (DIP) serially interfaced 8-digit LED display driver to control a 8x8 LED matrix, but the idea will be more or less the same.

   Each byte its bits represents the status of LED: 0=OFF, 1=ON.
   This test will only light up 2 LEDS (see circuit).
   e.g.
   11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111 lights up all LEDs
   01010000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 lights up the 2nd and the 4th LED
   000000000000 shut off all LEDs
   The circuit:
   - LED 1 (RED) to digital pin 2, with 220 Ohm resistor
   - LED 2 (GREEN) to digital pin 4, with 220 Ohm resistor

   Created 2016/02/04
   By Maarten Van Damme
   Modified
   By Maarten Van Damme
   2017/02/05

   http://projects.familievandamme.be

*/
byte buffer[9];//One character bigger than the intended number of characters.
int received;

int redLed = 2;
int greenLed = 4;

void setup() {

  received = 0;
  buffer[received] = '\0';

  Serial.setTimeout(200);
  Serial.begin(9600);
  pinMode(redLed, OUTPUT);
  pinMode(greenLed, OUTPUT);
}

void loop() {

  if (Serial.available())
  {
    buffer[received++] = Serial.read();
    buffer[received] = '\0';

    //When all 8 bytes have been received
    if (received >= (sizeof(buffer) - 1))
    {
      received = 0;

      int currentLED = 0;//Start with digitalPin 1

      //Loop over all bytes received (1 byte = 1 matrix row)
      for (int i = 0; i < sizeof(buffer) - 1; i++)
      {
        //For each byte, loop over all bits (1 byte = 1 column of the current matrix row)
        for (int j = 0; j < 8; j++)
        {
          //Whhile the MAX7219ENG is not in the circuit, only a limited set of pins can be controlled without bumping into some errors in the Arduino code.
          if (currentLED < 12)
          {
            currentLED++;
          }

          // Serial.print("LED: ");
          // Serial.print(currentLED);
          // Serial.print(": ");
          // Serial.print(bitRead(buffer[i], j));
          // (bitRead(buffer[i], j) == 1 ? Serial.println(" --> ON") : Serial.println(" --> OFF"));

          //1 = HIGH, 0 = LOW
          digitalWrite(currentLED, bitRead(buffer[i], j)) ;

        }
      }
      //Serial.print("#");//Inform all bytes were handled. Next byte can be sent.
    }
  }
}

The Java code was also slightly updated (ugly as always, and definitely to be improved a lot):

package be.familievandamme.projects.ka350i.arduino;

import java.util.BitSet;

import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortEvent;
import com.fazecast.jSerialComm.SerialPortPacketListener;

public class ArduinoWriteJSerialCommTest_BITS implements SerialPortPacketListener {

  static boolean readyToWrite = true;

  public static void main(String args[]) {

    SerialPort[] computerPorts = SerialPort.getCommPorts();
    SerialPort selectedPort = null;

    for (SerialPort p : computerPorts) {
      if (p.getSystemPortName().equals("COM4")) {
        selectedPort = p;
      }
    }

    // Try to open port, terminate execution if not possible
    if (selectedPort == null) {
      return;

    } else if (selectedPort.openPort()) {
      System.out.println(selectedPort.getSystemPortName() + " successfully opened.");

    } else {
      System.out.println(selectedPort.getSystemPortName() + " failed to open.");
      return;
    }

    // Add listener for incoming data
    ArduinoWriteJSerialCommTest_BITS sc = new ArduinoWriteJSerialCommTest_BITS();
    selectedPort.addDataListener(sc);

    selectedPort.setBaudRate(9600);
    selectedPort.setNumDataBits(8);

    int counter = 0;

    try {

      Thread.sleep(100);
      byte[] bytesToWrite = new byte[8];
      Thread.sleep(100);

      for (int i = 0; i < 200; i++) {

        try {

          // New BitSet has by default 0 for all bits contained in the
          // BitSet.
          BitSet bs = new BitSet();

          // Alternate 0 and 1 values
          if (i % 2 == 0) {
            // Second bit
            bs.set(1);
            System.out.println("LED1: ON");
            counter++;
          } else {
            // 4th bit
            bs.set(3);
            System.out.println("LED2: ON");
            counter++;
          }

          bytesToWrite = bs.toByteArray();

          // Always ensure 8 bytes are sent
          selectedPort.writeBytes(bytesToWrite, 8);

          // Depending on how fast the 'other' side can handle the
          // data sent, a small delay will be required.
          Thread.sleep(100);

        } catch (Exception e) {
          System.out.println("Failed to send");
        }

      }

      selectedPort.closePort();
      System.out.print("Counter: " + counter);

    } catch (Exception e) {
      e.printStackTrace();
      selectedPort.closePort();
    }

    selectedPort.closePort();
  }

  @Override
  public int getListeningEvents() {
    return SerialPort.LISTENING_EVENT_DATA_RECEIVED;
  }

  @Override
  public int getPacketSize() {
    return 1000;
  }

  @Override
  public void serialEvent(SerialPortEvent event) {
    byte[] newData = event.getReceivedData();
    System.out.println("Received data of size: " + newData.length);
    for (int i = 0; i < newData.length; ++i)
      System.out.print((char) newData[i]);
    System.out.println("\n");
  }

}

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *