HPA controller build

dstroy

Insanely Active Member
Got the INA260s in. The library for this one is ok, no changes for my implementation necessary.
 

dstroy

Insanely Active Member
Working on the m4 express this morning, i2c is very temperamental on the samd51 compared to the mega. The wire library is a different fork and they had some problems with illegal sercom combinations which would cause the i2c bus to lock up.

It also doesn't like certain master/slave combinations for whatever reason. Ok no problem the only thing I'm using it for is the RTC for a "system time" time stamp, which helps line up log messages and events from the different microcontrollers.

I'm just making it tolerant of unstable i2c bus, there are only a couple of use cases possible (in my design) where the i2c bus loses power but this controller doesn't.
 

dstroy

Insanely Active Member
lol

Code:
void calc_leaf_temp() {
  //0x4a
  //ain0 100.5k
  //   1 100.2k
  //   2 101.2k
  //   3 100.1k
  //
  //0x49
  //ain0 100.9k
  //   1 103.2k
  //   2 099.7k
  //   3 099.9k



  // resistance at 25 degrees C
#define THERMISTORNOMINAL 100000
  // temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25
  // how many samples to take and average, more takes longer
#define NUMSAMPLES 5
  // The beta coefficient of the thermistor 
#define BCOEFFICIENT 3950

  //series resistor values
  //"area one"
#define ADS_ONE_AIN0_R 100900
#define ADS_ONE_AIN1_R 103200
#define ADS_ONE_AIN2_R 99700
#define ADS_ONE_AIN3_R 99800
  //"area two"
#define ADS_TWO_AIN0_R 100500
#define ADS_TWO_AIN1_R 100200
#define ADS_TWO_AIN2_R 101200
#define ADS_TWO_AIN3_R 100100

//todo
//pop with macros
  const unsigned long SERIES_RESISTOR_VALUES[8] = {100900, 103200, 99700, 99800,
                                                   100500, 100200, 101200, 100100
                                                  };
  
//todo
//per channel temperature offset, offload to config
  const float offset[8] = {0};



//func var
//sentinel
  static int prev_ads_samples = 0;
//2d array, 8 sensors 5 samples each  
static long samples[8][NUMSAMPLES] = {0};
//working variables  
float average[8] = {0};
  float steinhart[8] = {0};


  // take N samples in a row
  if (cEnvir.ads_samples != prev_ads_samples) {
    prev_ads_samples = cEnvir.ads_samples;
    if (cEnvir.ads_samples <= NUMSAMPLES) {
      //Serial.print(AreaOne.ads_raw[0]);
      samples[0][cEnvir.ads_samples - 1] = AreaOne.ads_raw[0];
      samples[1][cEnvir.ads_samples - 1] = AreaOne.ads_raw[1];
      samples[2][cEnvir.ads_samples - 1] = AreaOne.ads_raw[2];
      samples[3][cEnvir.ads_samples - 1] = AreaOne.ads_raw[3];

      samples[4][cEnvir.ads_samples - 1] = AreaTwo.ads_raw[0];
      samples[5][cEnvir.ads_samples - 1] = AreaTwo.ads_raw[1];
      samples[6][cEnvir.ads_samples - 1] = AreaTwo.ads_raw[2];
      samples[7][cEnvir.ads_samples - 1] = AreaTwo.ads_raw[3];

      //      Serial.print("debug samples ");
      //      Serial.print(samples[7][0]);Serial.print(",");
      //      Serial.print(samples[7][1]);Serial.print(",");
      //      Serial.print(samples[7][2]);Serial.print(",");
      //      Serial.print(samples[7][3]);Serial.print(",");
      //      Serial.print(samples[7][4]);Serial.println(" ");
    }
    //if we have the samples
    if (cEnvir.ads_samples > (NUMSAMPLES - 1)) {
      Serial1.print(F("k "));
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 5; j++) {
          average[i] += float(samples[i][j]);
        }
        average[i] /= float(cEnvir.ads_samples);
//        Serial.print("Sensor : ");
//        Serial.print(i);
//        Serial.print(" , average analog reading ");
        Serial.println(average[i]);

        // convert the value to resistance
        average[i] = 32766 / average[i] - 1;
        average[i] = float(SERIES_RESISTOR_VALUES[i]) / average[i];
//        Serial.print("Thermistor resistance ");
        Serial.println(average[i]);

        steinhart[i] = average[i] / float(THERMISTORNOMINAL);
        steinhart[i] = log(steinhart[i]);
        steinhart[i] /= BCOEFFICIENT;
        steinhart[i] += 1.0 / (float(TEMPERATURENOMINAL) + 273.15);
        steinhart[i] = 1.0 / steinhart[i];
        steinhart[i] -= 273.15;
//        Serial.print("Temperature ");
        Serial.println(steinhart[i]);
//        Serial.println(" *C");
        Serial1.print(steinhart[i]);Serial1.print(F(","));
      }
      Serial1.print(F("\r\n"));
      for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 5; j++) {
          samples[i][j] = 0;
        }
      }
      cEnvir.ads_samples = 0;
    }
  }
}
the mega gets the raw input from two ads1115 for a total of eight temperature sensors (absolute leaf temp), sends the raw adc to the m4 over ttl serial, the m4 does the business and sends back the leaf temperature to get put into the environmentals log message
 

dstroy

Insanely Active Member
dc ssr code, mega2560

Code:
void dc_solid_state_relay() {
  processCommand();
  /*
    PORTC = PORTC & B11000000; //30,31 LOW (DC SSR 1, 2)
    PORTA = PORTA & B00000011; //set pins 22, 23 LOW (DC SSR 3, 4)
    PORTL = PORTL & B00001111; //46,47,48,49 LOW (DC SSR 5,6,7,8)

    how to turn pins on or off with port manipulation
    turn it off
    PORTL &= ~(1 << PL5); //PL5 LOW
    turn it on
    PORTL |= (1 << PL5); //PL5 HIGH

    check pin state
    if ((PINC & B10000000) == B10000000) {do things}
    if pin register c bit 7 (aka PC7) is high  {do things}
  */

  switch (data[0]) {
    case 1: {
        //PINC PC7 DC SSR 1 digital pin 30
        //if the pin is high, make it low
        if ((PINC & B10000000) == B10000000) {
          PORTC &= ~(1 << PC7);
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_ONE_OFF\"}}\r\n"));
        }
        //else make it high
        else {
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_ONE_ON\"}}\r\n"));
          PORTC |= (1 << PC7);
        }
        break;
      }
    case 2: {
        if ((PINC & B01000000) == B01000000) {
          PORTC &= ~(1 << PC6);
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_TWO_OFF\"}}\r\n"));
        }
        else {
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_TWO_ON\"}}\r\n"));
          PORTC |= (1 << PC6);
        }
        break;
      }
    case 3: {
        if ((PINA & B00000001) == B00000001) {
          PORTA &= ~(1 << PA0);
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_THREE_OFF\"}}\r\n"));
        }
        else {
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_THREE_ON\"}}\r\n"));
          PORTA |= (1 << PA0);
        }
        break;
      }
    case 4: {
        if ((PINA & B00000010) == B00000010) {
          PORTA &= ~(1 << PA1);
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_FOUR_OFF\"}}\r\n"));
        }
        else {
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_FOUR_ON\"}}\r\n"));
          PORTA |= (1 << PA1);
        }
        break;
      }
    case 5: {
        if ((PINL & B00000010) == B00000010) {
          PORTL &= ~(1 << PL1);
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_FIVE_OFF\"}}\r\n"));
        }
        else {
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_FIVE_ON\"}}\r\n"));
          PORTL |= (1 << PL1);
        }
        break;
      }
    case 6: {
        if ((PINL & B00000001) == B00000001) {
          PORTL &= ~(1 << PL0);
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_SIX_OFF\"}}\r\n"));
        }
        else {
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_SIX_ON\"}}\r\n"));
          PORTL |= (1 << PL0);
        }
        break;
      }
    case 7: {
        if ((PINL & B00001000) == B00001000) {
          PORTL &= ~(1 << PL3);
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_SEVEN_OFF\"}}\r\n"));
        }
        else {
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_SEVEN_ON\"}}\r\n"));
          PORTL |= (1 << PL3);
        }
        break;
      }
    case 8: {
        if ((PINL & B00000100) == B00000100) {
          PORTL &= ~(1 << PL2);
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_EIGHT_OFF\"}}\r\n"));
        }
        else {
          timeStamp();
          Serial.print(F("\"SYS\":\"DC_SSR_EIGHT_ON\"}}\r\n"));
          PORTL |= (1 << PL2);
        }
        break;
      }
    default: {
        timeStamp();
        Serial.print(F("\"ERROR\":\"INPUT_ERROR\"}}\r\n"));
        break;
      }
  }
}
 

dstroy

Insanely Active Member
Man, I was chasing my tail for a little bit this morning.

I wasn't paying attention to message length and was overflowing the buffer on the mega's hardware serial. fun times, the default buffer size is 64, I was sending a 103 char message... chaos ensued until I got a look at what I was transmitting and receiving, then I realized what was happening.

Works fine now:
1581615024004.png

the m4 does the heavy lifting and sends back the result to the mega, which puts it in the log message

why not have the m4 print out log messages too? It does, but not environmental log messages, those come from one place only.

now I have air vpd, and 4 leaf vpd (5 separate vpd), I'll place the leaf temp sensors at different locations in the canopy

TL;DR buffer overflow bad!
 
Top