3w 8x8 LED Dome+IR Nikon trigger: my code is ugly, help it to elegance

Greetings from Islamabad, Pakistan!

I am trying to make a Dome with 64 3W LEDs in an 8X8 matrix driven by an Arduino Mega 2650 with the help of intermediate MOSFETs for higher current supplies. Here is what I am trying to make: https://cias.rit.edu/media/uploads/projects/1533/documents/275/kinsman-rti-6625-47322-1-pb.pdf!

However, I needed higher powered LEDs to keep exposure times short so went for a direct driven matrix. Am an absolute beginner. Tried learning following tutorials and books and research as much as I could. Driving an LED Matrix Directly on the Arduino (http://playground.arduino.cc/Main/DirectDriveLEDMatrix) would have done it had I been able to understand. I could not.

Still I have written a fair bit of code that I reckon should do the trick for me. However, I am not happy with the plebian character of my code for do understand that if I knew better the whole process could be coded in a few lines of code and very very elegantly. But I did what I could and it is attached herewith for I do not wish to paste a whole lot of repetitive code to offend your --I imagine-- very evolved programming aesthetics! :slight_smile:

I am making this to introduce PTM/RTI photography --Polynomial Texture Mapping/Reflectance Transfer Imaging–in Pakistan and also to practice it as a professional.

Will very much appreciate if one of the learned ones on this forum help me make my code as it should be instead of the rudimentary logic that is contained in my repetitious take here!

Best regards.

Khalid Hussain,
Banigala, Islamabad, Pakistan

Draft_Code.txt (15.8 KB)

If you are driving the LEDs with 5V you can use P-Channel MOSFETs for the high-side drivers and N-Channel MOSFETs for the low-side drivers. Set one high-side output pin LOW and one low-side output pin HIGH to turn on the LED at that intersection. You will need a resistor current limiter on each row or each column.

Thank you very much. Appreciated. I will surely do that!

Meanwhile, my code is really tardy though it has compiled on the IDE. I will appreciate if you and other seasoned programmers could help me improve it.

Best regards.

Khalid Hussain
Islamabad, Pakistan.

DomeLight.ino (12.8 KB)

Your code has many errrors, for example


  digitalWrite( row[8], LOW);  // ups, maxindex is 7
  digitalWrite( col[16], HIGH); // ups, maxindex is 7

It delays through the steps, which are generated by paste and copy.

The pixels array is not really used, all elements are always HIGH and never read.

Integers are used to hold a bit.

All strings waste RAM, because you didn’t use the F() macro.

This is my version of your code (I kept the unused pixel array)

// idea: SHAD LED Array Dome, www.shad.org.pk
// http://sebastian.setz.name/arduino/my-libraries/multi-camera-ir-control/

#include <Wire.h>
#include <multiCameraIrControl.h>

bool sequenceRunning;
byte currentStep;
unsigned long lastStep;
const unsigned int stepDuration = 3000;

Nikon Camera(0); // Infrared LED as camera trigger

const byte col[8] = {1, 2, 3, 4, 5, 6, 7, 8}; // col[xx] on led matrix
const byte row[8] = {9, 10, 11, 12, 13, 14, 15, 16}; // row[xx] on led matrix

int pixels[8][8];

void setup() {
  Serial.println(F("SHAD PTM/RTI Dome"));
  pinMode(8, OUTPUT); // for tone
  // initialize the I/O pins as outputs
  for (int thisPin = 0; thisPin < 8; thisPin++) {
    // initialize the output pins:
    pinMode(col[thisPin], OUTPUT);
    pinMode(row[thisPin], OUTPUT);
    // take the col pins cathodes) high to ensure that the LEDS are off
    digitalWrite(col[thisPin], HIGH);
  Serial.println(F("send 'a' to start"));

void shootPixel(byte pixNum) {
  byte rIdx = pixNum & 0x7;
  byte cIdx = pixNum >> 3;
  digitalWrite( row[rIdx], LOW);    // the anode  low
  digitalWrite( col[cIdx], HIGH);   // the cathode high -- this turns the LED on
  pixels[rIdx][cIdx] = HIGH;

void loop() {
  unsigned long topLoop = millis();
  if (Serial.available()) {
    char currChar = Serial.read();
    if (tolower(currChar) == 'a') { // a A on
      if (!sequenceRunning) {
        currentStep = 0;
        sequenceRunning = true;
        tone(8, 3000, 150);
        Serial.println(F("Shooting Session Begins"));
  if (sequenceRunning && ((currentStep == 0) || (topLoop - lastStep >= stepDuration))) {
    lastStep = topLoop;
    Serial.print(F("step "));
    if (++currentStep >= 8 * 8) {
      sequenceRunning = false;
      Serial.println(F("Camera sequence complete"));
      Serial.println(F("Waiting for the next session"));
      Serial.println(F("send 'a' to start"));
      tone(8, 3000, 150);
send 'a' to start
Shooting Session Begins
step 0
step 1
step 2
step 3
step 4
step 5
step 6
step 7
step 8
step 9
step 10
step 11
step 12
step 13
step 14
step 15
step 16
step 17
step 18
step 19
step 20
step 21
step 22
step 23
step 24
step 25
step 26
step 27
step 28
step 29
step 30
step 31
step 32
step 33
step 34
step 35
step 36
step 37
step 38
step 39
step 40
step 41
step 42
step 43
step 44
step 45
step 46
step 47
step 48
step 49
step 50
step 51
step 52
step 53
step 54
step 55
step 56
step 57
step 58
step 59
step 60
step 61
step 62
step 63
Camera sequence complete
Waiting for the next session
send 'a' to start

I am in awe of your generosity Mr. Whandall as well as your obvious capacity to write beautiful code. And am extremely obliged and do very much appreciate your kindness.

I am fast looking up references to understand F() Macro and the rest of your exquisite code though I believe it will work like a charm. It will obviously take me some time to understand and am in the process to learn but am grateful that you took the time to help me out here. I thought the second iteration of my code (DomeLight.ino) was functionally correct because the Arduino IDE did compile it without generating errors and I certainly do not know better! :slight_smile:

I will study to understand your code and will also try it in my circuit. I am going to buy the electronics today. That will be one Mega 2650+8 N Mosfets+8 P Mosfets (generous advice from johnwasser above) +1 ohm Resistors+64 star mounted LEDs+two one amp power supplies with 3.6 volt out each which means a one ohm resistor is all I will need.

I am sure it will work out swell. Will keep you posted.

Stay very blessed.


Dear Mr. Whandall,

Greetings from Islamabad, Pakistan!

I am grateful for you kind help and generous guidance with your exquisite code. I spent the whole day studying and educating myself how your code works. I needed to do that to be able to understand the logic of your code so that I could ask you for clarifications if needed. I really appreciate this tuition for it allowed me to reference a lot of stuff that I am still trying to grapple with being new to coding and electronics. In the process, I have put in many an observations on your lines of code to show my appreciation of it. These appear as comments in the file attached herewith in which most of your comments I have deleted so that you can see my feedback without having to go through extra lines of text.

My only question is about the use of pin 8 for the tone output as we also use the same pin in our matrix. Should I change it to an unused pin?

Also, I was confused about the character strings you shared in the second code window and that i had copied in the same file as the code. I studied the F() macro function, its syntax and usage but couldn’t find any references to the character strings you shared. It was sheer common sense that allowed me to imagine that these were the output character arrays from the Serial.print(F("step ")) and Serial.println(currentStep) lines of code. Do correct me if I am wrong in my understanding and these character arrays are to be used some how!

I will try to finish the electronics circuits tomorrow so that I can share how the code worked in real life!

My very best regards to you.

Khalid Hussain
Islamabad, Pakistan.

DomeLight_Whandall_Code_Comments.txt (4.42 KB)

My only question is about the use of pin 8 for the tone output as we also use the same pin in our matrix. Should I change it to an unused pin?

Yes. I didn't notice the duplicate pin, sorry.

The F() macro places the string in PROGMEM and generates a type that the print functions can distinguish from
normal char arrays and use the extra code to fetch the data from PROGMEM. That is the Arduino way(* see notes below).

If you do not use this macro (or other means to place the strings in PROGMEM),
the strings end in RAM and consume it pretty fast.

There are 64 different bit patterns (6 bit long), each corresponding to a single LED.
We can use the number of the led to map directly to a row (lower 3 bits) and column (upper 3 bits).
We get the column index by shifting the number 3 positions down and the row index by masking with 7.
Both indices are used to select the correct digital pins from arrays.

  digitalWrite( row[ pixNum & 0x7 ], LOW);  // the anode  low
  digitalWrite( col[ pixNum >> 3 ], HIGH);  // the cathode high -- this turns the LED on

To make the sequence start directly,

  if (sequenceRunning && ((currentStep == 0) || (topLoop - lastStep >= stepDuration))) {

the currentStep==0 disables the delayed execution for the first step.

The attached output is what I get when I run the sketch.
I just wanted to make shure that all works as expected.

If you need more clarification, just ask.

(*) Additional infos about PROGMEM handling just for completeness:

There is a PSTR() macro that works like the F() but without a special type,
so it needs special functions to access the correct address space. That's the AVR way.
There are variants of C string manipulation functions, that deal with strings in PROGMEM.

I am extremely grateful for the time and consideration you have so generously given in guiding me. It is very much appreciated. I stand educated besides being a very happy beneficiary of your kindness.

I will put the code to test in my circuit today or max by tomorrow and will revert with the results.

Stay blessed!

Khalid Hussain
Islamabad, Pakistan.

I think I forgot to reset the pins, so you you should add a call to

void resetPins() {
  // take the col pins (cathodes) high row pins (anodes) low to ensure that all LEDS are off
  for (int thisPin = 0; thisPin < 8; thisPin++) {
    digitalWrite(col[thisPin], HIGH);
    digitalWrite(row[thisPin], LOW);

when appropriate.

That could be before setting the new col and row, or after taking the shot.

Thank you very much Mr. Whandall. Appreciated. Will revert with the results as am still procuring parts to check the circuit on the bread board. Will share the results shortly!

Best regards.

Khalid Hussain,
Islamabad, Pakistan.