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"); } }