Questions about programming

theskaz
Posts: 22
Joined: Mon Feb 13, 2017 5:22 pm

Questions about programming

Postby theskaz » Tue Feb 28, 2017 8:05 pm

Hello,

As i have mentioned before, I am a c# developer trying to get an ESP32 to do a lot it seems. Since I started with the Arduino, I stuck with the arduino IDE. I have questions around general c/c++ programming, and some stuff specific to the ESP32 using Arduino core.

What i am trying to accomplish:

Use an esp32 that has an ILI9341 display to control 4 SSRs, read from 4 temp sensors (1-wire), act as a PID for 2 of those SSRs, Publish and Subscribe to a Mosquitto Broker (that is in place already) over TLS 1.2 and using authentication....

I think that is it...

first off, my includes:

Code: Select all

#include <PID_v1.h>
#include <PubSubClient.h>
#include <Preferences.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <SPI.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_GFX.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <gfxfont.h>
#include <Adafruit_FT6206.h>
#include "certificates.h"
so you know what I am dealing with.

#1 - Is it better to declare all variables globally (if you can)? or use that sparingly? I have 120 lines of either variables, or #declare statements

#2 - I want to be able to grab user input the instant it happens, either through the mqtt broker or the touchscreen, would it be best to do events, or interrupts, or something else?

#3 - is there a way for me to be able to keep an eye on the heap/ram/etc. I ask that because after a little bit, my screen goes white, but the broker is still receiving data. then the whole thing will reboot.

Hans Dorn
Posts: 62
Joined: Tue Feb 21, 2017 2:21 am

Re: Questions about programming

Postby Hans Dorn » Tue Feb 28, 2017 9:38 pm

Hi.

#1: You cold try to group your variables together via structs or even better classes

#2: A lot of arduino functions won't work properly in an interrupt handler.
Unless you're aiming for sub millisecond response times, better try something else ;)


#3: "ESP.getFreeHeap()" will tell you the amount of available memory.

Cheers

theskaz
Posts: 22
Joined: Mon Feb 13, 2017 5:22 pm

Re: Questions about programming

Postby theskaz » Tue Feb 28, 2017 9:48 pm

Thank you. I thought about setting up something similar to wrapper classes or inherited classes, but havent figured out classes in c.

as for interrupts, The only thing that I need immediate response is for touchscreen input. in the onewire library it takes about 750ms just to get temps, so that slows things down a bit, and would like to bypass that somehow. here is my loop()

Code: Select all

if (!client.connected()) {
		reconnect();
	}
	client.loop();
	long now = millis();
	if (now - lastMsg > 2000) {
		lastMsg = now;
		publishTemps();
	}
	if (ts.touched())
	{
		TS_Point p = ts.getPoint();
		//rotate y axis.... i dont know why Y0 is far right and Y320 is far left
		p.y = map(p.y, 0, 320, 320, 0);

		// Print out the remapped (rotated) coordinates
		Serial.print("("); Serial.print(p.x);
		Serial.print(", "); Serial.print(p.y);
		Serial.println(")");
		if ((p.x >= BOIL_ELEMENT_STAT_X && p.x <= BOIL_ELEMENT_STAT_X + BOIL_ELEMENT_STAT_W) && (p.y >= BOIL_ELEMENT_STAT_Y && p.y <= BOIL_ELEMENT_STAT_Y + BOIL_ELEMENT_STAT_H)) {
			changeStateOfBoiler();
		}
	}

	updateRssi();
	updateAmps();
	updateTemps();
and in updateTemps():

Code: Select all

	sensors.requestTemperatures(); //750ms

	int oldHltTemp = hltTemp;
	int oldMltTemp = mltTemp;
	int oldBoilTemp = boilTemp;
	int oldAmbientTemp = ambientTemp;

	int localHltTemp = round(sensors.getTempFByIndex(0));
	if (localHltTemp > (int)(-100))
	{
		hltTemp = localHltTemp;
		if (oldHltTemp != hltTemp) {
			updateHltTempDisplay(oldHltTemp);
		}
	}
	int localMltTemp = round(sensors.getTempFByIndex(1));
	if (localMltTemp > (int)(-100)) {
		mltTemp = localMltTemp;
		if (oldMltTemp != mltTemp) {
			updateMltTempDisplay(oldMltTemp);
		}
	}
	int localBoilTemp = round(sensors.getTempFByIndex(2));
	if (localBoilTemp > (int)(-100))
	{
		boilTemp = localBoilTemp;
		if (oldBoilTemp != boilTemp) {
			updateBoilTempDisplay(oldBoilTemp);
		}
	}
	int localAmbientTemp = round(sensors.getTempFByIndex(3));
	if (sensors.getTempFByIndex(3) > (int)(-100))
	{
		ambientTemp = localAmbientTemp;
		if (oldAmbientTemp != ambientTemp) {
			updateAmbientTempDisplay(oldAmbientTemp);
		}
	}
do you have any ideas on how I can adjust this?

Hans Dorn
Posts: 62
Joined: Tue Feb 21, 2017 2:21 am

Re: Questions about programming

Postby Hans Dorn » Tue Feb 28, 2017 11:01 pm

Hi,

I didn't even know that the OneWire library works on the ESP32. :)

I'll give it a try as I have couple of DS18B20 sitting around.

I'll get back at you after I get the sensors running.

Hans Dorn
Posts: 62
Joined: Tue Feb 21, 2017 2:21 am

Re: Questions about programming

Postby Hans Dorn » Wed Mar 01, 2017 12:43 am

OK, here we go :)

The arduino libs worked right out of the box, I love this stuff!

You're in luck, the DallasTemperature lib supports asynchronous operation.
You just have to take care you don't call "requestTemperatures" faster than the sensors can keep up with.

I've appended a little sketch for one sensor, pulled straight from the examples and modified for async reads.
There's some additional timing info too.

You'll probably want to put the call to "getTempC" right in front of the requestTemperatures call.
I called it more often than needed to see if something breaks.

Cheers
Hans

Code: Select all

#include <DallasTemperature.h>
#include <OneWire.h>

#define ONE_WIRE_BUS 25

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// arrays to hold device address
DeviceAddress insideThermometer;


void setup() {

  Serial.begin(115200);
  delay(100);
  
  Serial.print("Locating devices...");
  sensors.begin();
  Serial.print("Found ");
  Serial.print(sensors.getDeviceCount(), DEC);
  Serial.println(" devices.");

  // report parasite power requirements
  Serial.print("Parasite power is: "); 
  if (sensors.isParasitePowerMode()) Serial.println("ON");
  else Serial.println("OFF");
  
  if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0"); 
  
  // show the addresses we found on the bus
  Serial.print("Device 0 Address: ");
  printAddress(insideThermometer);
  Serial.println();

  // set the resolution to 12 bit (Each Dallas/Maxim device is capable of several different resolutions)
  sensors.setResolution(insideThermometer, 12);
 
  Serial.print("Device 0 Resolution: ");
  Serial.print(sensors.getResolution(insideThermometer), DEC); 
  Serial.println();

  // enable async mode. Take care you put enough time between calls to "requestTemperatures"
  sensors.setWaitForConversion(false); 

}

uint32_t inline IRAM_ATTR cycles()
{
    uint32_t ccount;
    __asm__ __volatile__ ( "rsr     %0, ccount" : "=a" (ccount) );
    return ccount;
}


// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{

  uint32_t t00, t01;

  t00 = cycles();
  float tempC = sensors.getTempC(deviceAddress);
  t01 = cycles();
  Serial.print("Temp C: ");
  Serial.print(tempC); Serial.print(" ");
  Serial.print("getTemp time [ms]: "); Serial.print((t01-t00-7) / 240000.0, 3); Serial.print(" ");
}


void loop(void)
{ 
  static uint32_t last_request = 0;

  uint32_t t00, t01;
  
  uint32_t now = millis();
  
  // check for wraparound, just in case...
  if (now < last_request)  {
    last_request = now;
  }
  
  // put some time between conversion requests
  if( (now - last_request) > 750) {
    Serial.print("Requesting temperatures...");

    t00 = cycles(); // Capture request time
    sensors.requestTemperatures(); // Send the command to get temperatures
    t01 = cycles();
    
    Serial.println("DONE");
    last_request = now;
  }
 
    
  printTemperature(insideThermometer); // Use a simple function to print out the data
  Serial.print("request time [ms]: "); Serial.print((t01-t00-7) / 240000.0, 3);
  Serial.println();

  // do other stuff here ;)
  delay(100);
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

theskaz
Posts: 22
Joined: Mon Feb 13, 2017 5:22 pm

Re: Questions about programming

Postby theskaz » Wed Mar 01, 2017 3:09 pm

This is a beautiful thing! I owe you a beer.

I am still trying to get it implemented in my code (I have other issues that Im trying to work out with the WiFi)

I had to do some googling to see what "static" meant in your context and found that the value of that static variable persists between calls. Here I am, thinking, that if you want a variable to persist its value it must be outside the function (global). That begs the question, in this case, is there a reason to use one over the other?

also, would you mind explaining what this is doing

Code: Select all

uint32_t inline IRAM_ATTR cycles()
{
	uint32_t ccount;
	__asm__ __volatile__("rsr     %0, ccount" : "=a" (ccount));
	return ccount;
}
It's greek to me.

Hans Dorn
Posts: 62
Joined: Tue Feb 21, 2017 2:21 am

Re: Questions about programming

Postby Hans Dorn » Wed Mar 01, 2017 11:47 pm

Static variables have the advantage that only the function that contains them may access them.
This makes naming them easier, and prevents unauthorized access to them.

Their main disadvantage is that things start falling apart quickly if you forget about your statics and start calling the same function
from different places.

Talk about unintened side effects ;)


Cheers

Who is online

Users browsing this forum: brebisson and 46 guests