[SOLVED] Looking for tips working with functions

Hi,

I’ve worked on a small weekend project. I connected a 8x8 led matrix with a MAX7219 controller to my photon. My software is exposing functions to display different symbols (heart, invader, etc.) on this matrix. I call those functions via particle cloud API to trigger the symbols. Everything worked out fine but I wonder if there are some creative out there, helping to optimise the following code. I want to make it more generic and flexible.

If I follow my current design (one function creates one symbol) I’m limited to 15 symbols, because the cloud allows to expose 15 functions.

To solve this I think about one generic function with a switch/case that receives a parameter. This brings me to one problem. Cloud functions expecting Strings datatypes and switch/cases work with integers. I found one possible solution with a mapping: Switch case & strings is this for my case the only way or are there some other ideas?

    // This #include statement was automatically added by the Particle IDE.
#include <LedControl-MAX7219-MAX7221.h>

LedControl *led;

int displayNone(String command);
int displayHeart(String command);
int displayInvader1(String command);

void setup() {
    led = new LedControl(A0,A2,A1,1); //DIN,CLK,CS,HowManyDisplays
    led-> shutdown(0,false); //Turn it on

    Particle.function("none", displayNone);
    Particle.function("heart", displayHeart);
    Particle.function("inv1", displayInvader1);
}

void loop() {
    
}

int displayHeart(String command){
    int i = 15;
    int j = 0;
    
    if(command == "heart"){
        led->setRow(0,0,28);
        led->setRow(0,1,62);
        led->setRow(0,2,126);
        led->setRow(0,3,252);
        led->setRow(0,4,252);
        led->setRow(0,5,126);
        led->setRow(0,6,62);
        led->setRow(0,7,28);
        led->setIntensity(0,15);
        
        while(j<=1000){
            while (i!=0){
                    led->setIntensity(0,i = i-1);
                    delay(50);
            }
            while (i<=15){
                    led->setIntensity(0,i = i+1);
                    delay(50);
            }
            j++;
        }
        return 1;
  }
  else return -1;
}

int displayInvader1(String command){
    int j = 0;
    
    if(command == "inv1"){
        while(j<=1000){
            led->setRow(0,0,24);
            led->setRow(0,1,220);
            led->setRow(0,2,54);
            led->setRow(0,3,95);
            led->setRow(0,4,95);
            led->setRow(0,5,54);
            led->setRow(0,6,220);
            led->setRow(0,7,24);
            led->setIntensity(0,7);
            
            delay(1000);
            
            led->setRow(0,0,152);
            led->setRow(0,1,92);
            led->setRow(0,2,182);
            led->setRow(0,3,95);
            led->setRow(0,4,95);
            led->setRow(0,5,182);
            led->setRow(0,6,92);
            led->setRow(0,7,152);
            led->setIntensity(0,7);
            
            delay(1000);
            
            j++;   
        }
        return 1;
  }
  else return -1;
}


int displayNone(String command){
    
    if(command == "none"){
        led->setRow(0,0,0);
        led->setRow(0,1,0);
        led->setRow(0,2,0);
        led->setRow(0,3,0);
        led->setRow(0,4,0);
        led->setRow(0,5,0);
        led->setRow(0,6,0);
        led->setRow(0,7,0);
        led->setIntensity(0,7);
        return 1;
  }
  else return -1;
}

What’s stopping you from converting that string (which could be a simple number) to an integer before running it through your switch ;)?

2 Likes

You could also send the binary data for your display as 8 HEX numbers (or one 16 HEX digit number) - or if you prefer BIN over HEX and can accept to lose the last pixel as 63 chars with 0 or 1 - to send any arbitrary 8x8 pattern.

void setup() {
  Particle.function("drawBMP", drawBitmap);
  Particle.function("drawSymbol", drawSymbol);
}

int drawSymbol(String symbol) {
  if (symbol.equalsIgnoreCase("heart") {
    ...
    return 1;
  }
  else if (symbol.equalsIgnoreCase("diamond") {
    ...
    return 2;
  }  
  ...
  else {
    return 0;
  }
  return -1;
}

int drawBitmap(String bmp) {
  for(int y=0; y < 8; y++) {
    uint8_t row = 0;
    if (bmp.startsWith("0x") {
      // expected format "0x0123456789abcdef
      row = (uint8_t)strtol((const char*)bmp.substring(y*2+2, (y+1)*2+2), NULL, 16);
    }
    else {
      // expected format "000000001111111100000000111111110000000011111111000000001111111"
      row = (uint8_t)strtol((const char*)bmp.substring(y*8, (y+1)*8), NULL, 2);
    }
    led->setRow(0, y, row);
  }
  return 0;
}

BTW, I found picturing binary patterns a lot easier with HEX numbers than with DEC since each HEX digit stands for four bits and hence it’s really easy to learn the 16 digits binary representation by heart and hence make up any binary pattern on the fly without calculator.

Also don’t delay the execution of Particle.function() callbacks that long.
Rather set the pattern(s) and a flag in there and then do any animation outside via loop() or a timer.


For bitmapping, you may want to be able to see what you get from your numbers, which can be easily achieved this way.

uint8_t bitmaps[][8] = 
{ 
  { 0b00011000 // = 0x18 =  24 
  , 0b11011100 // = 0xDC = 220
  , 0b00110110 // = 0x36 =  54
  , 0b01011111 // = 0x5F =  95
  , 0b01011111 // = 0x5F =  95
  , 0b00110110 // = 0x36 =  54
  , 0b11011100 // = 0xDC = 220
  , 0b00011000 // = 0x18 =  24 
  } 
, { 0b10011000 // = 0x98 = 152
  , 0b01011100 // = 0x5C =  92
  , 0b10110110 // = 0xB6 = 182
  , 0b01011111 // = 0x5F =  95
  , 0b01011111 // = 0x5F =  95
  , 0b10110110 // = 0xB6 = 182
  , 0b01011100 // = 0x5C =  92
  , 0b10011000 // = 0x98 = 152
  }
, { 
...
  } 
};
3 Likes

@Moors7: stupid me… sometimes you can’t see wood for the trees.

@ScruffR: Thank you for this awesome reply… this will bring my solution to a complete new level. The binary way is fantastic so I can use the output of tools like http://www.pial.net/tools/ directly.

Thank you guys.

1 Like