Help Converting to Arduino?

edited January 2017 in Arduino

I would appreciate some help (or direction) converting this perfect Processing code to an Arduino Sketch? It is the color conversion math/function I cannot seem to get through.

I have been through a lot of permutations with Linux/Windows platforms and SBCs' but the Arduino IDE and like microcontrollers seems to be the best option for this application.

Any help would be appreciated.

Thanks in Advance,

Ken

void applyColor() {  // Generate the heat map
  pushStyle(); // Save current drawing style
  // Set drawing mode to HSB instead of RGB
  colorMode(HSB, 1, 1, 1);
  loadPixels();
  int p = 0;
  for (int r = 0; r < height; r++) {
    for (int c = 0; c < width; c++) {
      // Get the heat map value
      float value = interp_array[c][r];
      // Constrain value to acceptable range.
      value = constrain(value, mintemp, maxtemp);
      // Map the value to the hue
      // 0.2 blue
      // 1.0 red
      value = map(value, mintemp, maxtemp, 0.2, 1.0);
      pixels[p++] = color(value, 1, 2);
    }
  }
  updatePixels();
  popStyle(); // Restore original drawing style
}

Answers

  • edited January 2017
    • Who invokes applyColor()? More specifically, which Thread is running it? /:)
    • Place println(Thread.currentThread()); as the 1st statement for your function applyColor().
    • If it doesn't display "Thread[Animation Thread,5,main]", you can't use any "drawing" API there! :-S
    • Surprisingly, even though color() doesn't draw anything, the way it was implemented, is unsuitable for concurrent access! 8-}
  • Apologies Mr. GoToLoop . . I do not understand these questions!

    • This is as far as I can help from the info you've posted.
    • I don't have the hardware, so I can't help you out further.
    • I don't get why you couldn't even typed in println(Thread.currentThread()); inside your applyColor()!
  • Ok, I think I understand. Will give it a try. Should I post the entire sketch for you to review?

  • Enough to know the context. And where variables are declared and initialized too.
    But as I've warned already, I don't have the hardware and thus my help is very limited! 8-|

  • So here it is in all its Glory! . . . Let me know if you can help with the conversion.

    Thanks,

    Ken

    import processing.io.*; I2C i2c;

    int r = 8;  // number of rows in input array
    int c = 8; // number of columns in input array
    int t = 60;  // parameter (array resize factor)
    int rows = (r-1)*t;  // height of the heat map
    int cols = (c-1)*t;  // width of the heat map
    float mintemp = 0;
    float maxtemp = 0;
    
    
    float[][] array;  // input array
    float[][] interp_array = new float[rows][cols]; // interpolated array
    
    void setup() {
      size(420, 420);
      frameRate(10);
      noStroke();
      i2c = new I2C(I2C.list()[0]);
    
      i2c.beginTransmission(0x68);
      i2c.write(0x02);
      i2c.write(0x01);
      i2c.endTransmission();
    
      i2c.beginTransmission(0x68);
      i2c.write(0x07);
      i2c.write(0x10);
      i2c.endTransmission();
    }
    
    void draw() {
      //  println();
      //  int startTime = millis();
      array = retrieveSensorData(); 
      //  println("retrieveSensorData() time: " + (millis()-startTime) + "ms");
      //  int beforeInterpolationTime = millis();
      bilinearInterpolation();
      //  println("bilinearInterpolation() time: " + (millis()-beforeInterpolationTime) + "ms");
      //  int beforeApplyColorTime = millis();
      applyColor();
      //  println("applyColor() time: " + (millis()-beforeApplyColorTime) + "ms");
      //  println("total time: " + (millis()-startTime) + "ms");
    }
    
    float[][] retrieveSensorData() {
      float[][] res = new float[r][c];
    
      float temp = 0;
      float temp1 = 0;
      mintemp = 0;
      maxtemp = 0;
      char addr = 0x68;
      int pixelTempL = 0x80;
    
      i2c.beginTransmission(addr);
      i2c.write(0x0E);
      i2c.endTransmission();
    
      i2c.beginTransmission(addr);
      i2c.write(0x0E);
      byte[] in1 = i2c.read(2);
      byte lowerLevel1 = in1[0];
      byte upperLevel1 = in1[1];
    
      //  print(lowerLevel1, "     ");
      //  print(upperLevel1, "     ");
    
      int temperature1 = ((upperLevel1<<8) | lowerLevel1);
      if (temperature1 > 2047) {
        temperature1 = temperature1 - 4096;
      }
      temp1 = abs(temperature1 * 0.25);
    
      print(temp1, "     ");
    
      for (int i=0; i<r; i++) {
        for (int j=0; j<c; j++) {
    
          i2c.beginTransmission(addr);
          i2c.write(pixelTempL);
          i2c.endTransmission();
    
          i2c.beginTransmission(addr);
          i2c.write(pixelTempL);
          byte[] in = i2c.read(2);
          byte lowerLevel = in[0];
          byte upperLevel = in[1];
    
          //   print(lowerLevel, "     ");
          //   print(upperLevel, "     ");
    
          int temperature = ((upperLevel<<8) | lowerLevel);
          if (temperature > 2047) {
            temperature = temperature - 4096;
          }
    
          temp = temperature * 0.25;
    
          res[i][j] = temp;
    
          if (j==0 && i==0) {
            mintemp = temp;
            maxtemp = temp;
          } else if (temp < mintemp) {
            mintemp = temp;
          } else if (temp > maxtemp) {
            maxtemp = temp;
          }
    
          pixelTempL = pixelTempL + 2;
        }
      }
      //  delay(800);
      return res;
    }
    
    void bilinearInterpolation() {  // Bi-linear Interpolation algorithm
    
      for (int i=0; i<r; i++) {
        for (int j=0; j<c; j++) {
          int x = j*t - 1;
          int y = i*t - 1;
          if (x<0)
            x=0;
          if (y<0)
            y=0;
          interp_array[y][x] = array[i][j];
        }
      }
    
      for (int y=0; y<rows; y++) {
        int dy1 = floor(y/(t*1.0));
        int dy2 = ceil(y/(t*1.0));
        int y1 = dy1*t - 1;
        int y2 = dy2*t - 1;
        if (y1<0)
          y1 = 0;
        if (y2<0)
          y2 = 0;
        for (int x=0; x<cols; x++) {
          int dx1 = floor(x/(t*1.0));
          int dx2 = ceil(x/(t*1.0));
          int x1 = dx1*t - 1;
          int x2 = dx2*t - 1;
          if (x1<0)
            x1 = 0;
          if (x2<0)
            x2 = 0;
          float q11 = array[dy1][dx1];
          float q12 = array[dy2][dx1];
          float q21 = array[dy1][dx2];
          float q22 = array[dy2][dx2];
    
          int count = 0;
          if (q11>0)
            count++;
          if (q12>0)
            count++;
          if (q21>0)
            count++;
          if (q22>0)
            count++;
    
          if (count>2) {
            if (!(y1==y2 && x1==x2)) {
    
              float t1 = (x-x1);
              float t2 = (x2-x);
              float t3 = (y-y1);
              float t4 = (y2-y);
              float t5 = (x2-x1);
              float t6 = (y2-y1);
    
              if (y1==y2) {
                interp_array[y][x] = q11*t2/t5 + q21*t1/t5;
              } else if (x1==x2) {
                interp_array[y][x] = q11*t4/t6 + q12*t3/t6;
              } else {
                float diff = t5*t6;
                interp_array[y][x] = (q11*t2*t4 + q21*t1*t4 + q12*t2*t3 + q22*t1*t3)/diff;
              }
            } else {
              interp_array[y][x] = q11;
            }
          } else {
            interp_array[y][x] = 0;
          }
        }
      }
    }
    
    void applyColor() {  // Generate the heat map
      println(Thread.currentThread());
        pushStyle(); // Save current drawing style
      // Set drawing mode to HSB instead of RGB
      colorMode(HSB, 1, 1, 1);
      loadPixels();
      int p = 0;
      for (int r = 0; r < height; r++) {
        for (int c = 0; c < width; c++) {
          // Get the heat map value
          float value = interp_array[c][r];
          // Constrain value to acceptable range.
          value = constrain(value, mintemp, maxtemp);
          // Map the value to the hue
          // 0.2 blue
          // 1.0 red
          value = map(value, mintemp, maxtemp, 0.2, 1.0);
          pixels[p++] = color(value, 1, 2);
        }
      }
      updatePixels();
      popStyle(); // Restore original drawing style
    }
    
  • edited January 2017 Answer ✓

    It is the color conversion math/function I cannot seem to get through.

    Do you understand how color works in processing?
    https://processing.org/reference/colorMode_.html

    As you see, the color is being managed by the processing engine. However, arduino does not process color, because it doesn't support it, it doesn't need to draw anything as I know that you are aware. Any color interpretation is for the user to implement.

    Looking at your code, you input data contains actual temperature data. You keep track of the min and max temperatures. Half part of the conversion done by looking at the code that your provided.

    The question is, what do you want for the output? You can output an array where min temp maps to 0.2 and max temp maps to 1.0. In the code you provided:

    pixels[p++] = color(value, 1, 2);
    

    Arduino does not have an equivalent for color. You need to come up with your own function. Notice you are using colorMode(HSB, 1, 1, 1); but you have a 2 in the previous line. Why 2? Your max range in your processing code for HSB color is 1 for each hue, saturation and brightness. In other words, your line in processing should read pixels[p++] = color(value, 1, 1);

    The following links shows that most of the conversion is already done for you as arduino provides equivalent functions:
    https://www.arduino.cc/en/Reference/Constrain
    https://www.arduino.cc/en/Reference/Map

    Next link is additional for you to consider, a way to manage the output array containing the heat map: http://arduino.stackexchange.com/questions/30205/returning-an-int-array-from-a-function

    The function you asked for would resembled the code below:

    //int *applyColor(float pix[width*height]) {  
    //EDITED  ***************
    float *applyColor(float pix[width*height]) {  
    
      int p = 0;
      for (int r = 0; r < height; r++) {
        for (int c = 0; c < width; c++) {      
          float value = interp_array[c][r];      
          value = constrain(value, mintemp, maxtemp);
          value = map(value, mintemp, maxtemp, 0.2, 1.0);
          pix[p++]=value;   // What application uses this data? 
        }
      }
    
      return pix;
    }
    

    Kf

  • Thank you for your responses and advice. I will look into the links you provide.

  • I think that the most important thing right now is how the data is being used. Can you shed some light on that?

  • The temperature data is used to generate a heatmap on a display screen . . . Is that not evident by the Processong sketch . . . Or am I misunderstanding your question?

  • edited January 2017

    No, how will the parsed data be used by the Arduino? As in, after converting your data on the Arduino into an array pix[] (using kfrajer's code), what do you plan to do with the array?

  • converting this perfect Processing code to an Arduino Sketch

    To me, this implies you are running everything on your arduino. Are you planning to send your data to Processing? Or are you planning to use your data to manage a grid of LEDs? It is not clear what you want to do with his information.

    Kf

  • Oh, ok, I understand what your asking. As in the Processing sketch, which has a "size (420,420)" to display the heat map, I will display on an TFT LCD of similar size.

    Also, I don't get that code posted by Kf . . . . Arduino IDE has a problem with it.

  • PS - all code will be run on the Arduino platform . . . No Processing!

  • Arduino IDE has a problem with it

    More details please.

    Kf

  • You'll have to remove the asterix from the the function name in kfrajer's code.

    To do what you're doing, you'll need to set up the tft library. Do that, get some experience in using a TFT screen before attempting this larger project.

  • edited January 2017

    Ok, thanks to all your help and advice I have made good progress in running this sketch on the Arduino . . . . I now realize I am spoiled by the rich color functions available in Processing.

    what I have to do now is convert the interpolated color, which was so conveniently done in Processing, and using what is available in C++ (Arduino IDE).

    Anyone interested in a challenge? :)

    Thanks Again to all who are responding . . . .

  • Notice, my function should return float and not an int array reference since pix is a float array. I will edit my post to reflect this change.

    @Lord_of_the_Galaxy I have not tested the code but I think you need to keep the asterix as I am returning an array. I a following the reference from http://arduino.stackexchange.com/questions/30205/returning-an-int-array-from-a-function Check title Have the caller manage the allocation.

    Kf

  • edited January 2017

    Oh, I didn't notice what you were rerurning.
    You don't even need to return it - you're editing the original array itself (assuming Arduino is based on C++, if it's based on C, then the process is different).

Sign In or Register to comment.