Go Down

Topic: MenWIZ using double instead of float (Read 655 times) previous topic - next topic

stretched59

Been at this Arduino stuff for about a month. Here is the project info:
Arduino UNO R3
Pololu Micro Serial Servo with 4 servos (expanding to 6 in final version)  on SoftwareSerial pin.
String of 5 Dallas 1 wire DS18B20 temp sensors (expanding to 7 in final version)
Freetronics LCD 16x2 shield with I2C backpack
5 buttons on analog pin
a couple of digital pins OUTPUT to control a fan, furnace and reset Pololu
a couple of digital pins INPUT to check if furnace is on

What this turns into is a 4 to 6 zone heat controller with PID control of the servos connected to dampers. Fan connected to duct work near the fireplace is turned on by a local temp sensor @ 70 degF or if the furnace is running. It is a functioning system without the menu or analog buttons.

I'm using the following libraries:

Code: [Select]
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <MENWIZ.h>
#include <PID_v1.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <SoftwareSerial.h>


What I am trying to do is use MenWIZ to display the 6 rooms information on a submenu and on another submenu adjust the 6 rooms setpoints.

My preferred method is to input the same variables that the PID's are using: Setpoint, Input and Output. The unfortunate part is that the PID vars are double types and MenWIZ requires float type. I can easily convert these to float by adding more variables to the program, however, I'm currently at 29,200 bytes and I haven't finished my menu yet. Any ideas on this one?

I'm also trying to display vars on 2 lines like this:
 
SP: 72       IN: 68
OUT: 95 %    //  this may end up as a 0-255 value instead.

I also need to be able to adjust the setpoint which is a double type.

Stupid question of the day: Since double and float are the same, according to the reference, why is double used so often? I suppose that I could hack the PID library.




WizenedEE

Use casts.

doubles are used more often because they are used more often in programming a PC because they're the same speed or faster on modern FPUs and are more accurate.

brunialti

Hi. I could add the double type to menwiz, but it would increase the footprint.
About the memory space, did you read the new doc where there are tips to reduce it quite a lot ?
- not using sprintf in the sketch saves 1.5 kB
- disabling  EEPROM based functions and BUTTON support (taht is you implement your own navigation device) save quite a lot of space

i hope this can  help.

stretched59

Oh yea, cast. I remember something about that in my java class. Finally a practical use for it. Adds more variables so my memory creeps up.

I have disabled eeprom and buttons since I am using using an analog input with 5 buttons. The analog sample I found used sprintf to display the usrScreen. I redid that part with sbuf.

I had been attempting to use phi_interface for the analog but the getKey was returning something that was close to the analog values instead of 1-5 like the class appeared to be programmed to return. So I ended up doing the same thing with the custom analog function and deleted phi. That's how I got to 29.2k.

Mega 2560 is in my future. Found some china clones on ebay for $22 last night. I think the real deal is a better choice.

I'll probably end up using some program on the laptop to graph the PID performance so I will be adding Ethernet and sd card. Memory creep.

Is there any method to get 3 variables displayed at the same time in the menu?


stretched59

#4
Jan 05, 2013, 03:07 am Last Edit: Jan 05, 2013, 03:39 am by stretched59 Reason: 1

Use casts.


I don't think this is going to work because I have to put the MENWIZ menu structure in setup() so it's a run once thing. If I have dynamic data, such as my room temp that I want to display.

I can see doing this for static double like my PID setpoint.

Slightly stripped down version here:

Code: [Select]

#include <Wire.h>  //INSERT ALL THE LIBARIES AFTER INCLUDING WIRE LIB (MENWIZ request)
#include <LiquidCrystal_I2C.h>
#include <MENWIZ.h>
#include <PID_v1.h>
#include <PID_v1.h>
// PID setup
const int numSensors = 4; // 4 temp sensors used with PID
double Input[numSensors]; // Arrays of 4 input and output variables
double Output[numSensors];
double Setpoint[numSensors] = {68, 72, 72, 72};
double kp = 3;
double ki = 5;
double kd = .1;
PID Room0(&Input[0], &Output[0], &Setpoint[0], kp, ki, kd, DIRECT);
PID Room1(&Input[1], &Output[1], &Setpoint[1], kp, ki, kd, DIRECT);
PID Room2(&Input[2], &Output[2], &Setpoint[2], kp, ki, kd, DIRECT);
PID Room3(&Input[3], &Output[3], &Setpoint[3], kp, ki, kd, DIRECT);

// Create global object for menu and lcd
menwiz menu;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Addr, En, Rw, Rs, d4, d5, d6, d7, backlightpin, polarity 4 x 20 LCD

// analog buttons sample
const int buttonPin = A0;             // 6 button switch circuit input connected to analog pin 0
boolean buttonBlock = 0;
boolean buttonAct = 0; // flag 1
boolean stopMenu = 0; // flag 2
byte buttonPressed = 0;  // which button was pressed
byte lastButtonPressed = 0; // prev button pressed
int buttonValue = 0;  // read value from analog port for the 4 navigation pushbuttons
long menuOffTime = 0;  //used for timer
extern byte MW_navbtn;  //needed to run the software key navigation in Menwiz

void setup()
{
   Serial.begin(9600);
   Serial.println("The Midway Zone Heat Control");

    //++++++++++++++++++++Menu and LCD 
  char b[84];
  _menu *r,*s1,*s2;
 
float room0SP = (float) Setpoint[0]; // cast operator

  // initialize the menu object ( 2 x rows x 16 columns LCD)
  menu.begin(&lcd,16,2);
  menu.addUsrNav(navMenu, 6);
  MW_navbtn=6;  // force 4 or 6 buttons mode for menu navigation -> MW_navbtn=4; or MW_navbtn=6;

  //create the menu tree
  r=menu.addMenu(MW_ROOT,NULL,F("MAIN MENU"));                      //create a root menu at first (required)

  //--------------- 
  s1=menu.addMenu(MW_SUBMENU,r,F("VIEW ROOM INFO"));
    s2->addItem(MW_LIST,F("SETPOINTS"));                          //create a variable of type "option list"..
        s2->addItem(MW_LIST,F("MASTER BEDROOM"));     //add option to the OPTION LIST
            // s2->addVar(MW_AUTO_FLOAT,Setpoint[0], 65, 75, 1);
}
void loop()

// NAVIGATION MANAGEMENT & DRAWING ON LCD. NOT BLOCKING has to be the first in the void loop
  menu.draw();
  navMenu();
}
 
  int navMenu() // 
{
  /*
   As soon as a button is pushed the first time flag 1 is set to HIGH and if the buttonnumber is not 0 then a timer is started.
   The menu action then should only be performed once.
   After 2000 msecs the flag will be set to LOW and a new buttonpush can be processed.
   Menu action is blocked for 2000 msec even if the same button is being kept pressed for 2000 msecs by flag2.
   */

  long menublockTime = millis();

  if (buttonAct == 1 && buttonPressed != 0 && stopMenu == 0)  // we have a state were we process a menu navigation step once and block it for 2 secs
  {
//   digitalWrite(led13Pin,HIGH);  // set timer led ON
    menuOffTime = menublockTime  + 2000; //start the timer. You can change this blocking time to your convenience but do not make it lower aa 200 msecs
    stopMenu = 1;

    switch (buttonPressed)
    {
    case 1: // Right
      return MW_BTR;
      break;
    case 2: // Up
      return MW_BTU;
      break;
    case 3: // Down
      return MW_BTD;
      break;     
    case 4: // Left
      return MW_BTL;
      break;
    case 5: // Select or Confirm
      return MW_BTC;
      break;
    case 6: // Escape NOT USED
      return MW_BTE;
      break;
    }
  }

  if (menuOffTime != 0  &&  menublockTime  > menuOffTime)  //  Reset of the timer so a new menu action can be processed
  {
    buttonAct = 0; // resets the flag 1
    buttonPressed = 0;
    menuOffTime = 0;  // resets timer to zero
    stopMenu = 0;

  }
}


If I wanted to display dynamic data I would have to use the cast operator at the end of the loop() and I assume that when menu.draw(); runs it will pull in the data. Am I thinking correctly?

Go Up