quadTC/quadTC.ino

193 lines
5.9 KiB
C++

#include <openGLCD.h>
#include "logo.h"
//----------------------------------------------------------------------------------
// CONSTANTES
//----------------------------------------------------------------------------------
#define VERSION "20180419"
#define MAX6675_CS0 13
#define MAX6675_CS1 12
#define MAX6675_CS2 3
#define MAX6675_CS3 2
#define MAX6675_SO 1
#define MAX6675_SCK 19
#define POTAR_PIN A7
#define LEN_PLOT 100
const byte X0Graph = 92;
const int T_REFRESH = 500;
const int T_SWITCH = 100;
//----------------------------------------------------------------------------------
// CLASSE PLOT
//----------------------------------------------------------------------------------
class Plot{
int y[LEN_PLOT]; // Tableau des valeurs stockées
public :
int y_min; // Min et max
int y_max; // (après avoir lancé AutoScale)
Plot(){
}
void AutoScale(){
int mini = 1024;
int maxi = 0;
for (int i = 0 ; i<LEN_PLOT ; i++){ // recherche min et max des points connus
if (y[i]<mini){mini = y[i];}
if (y[i]>maxi){maxi = y[i];}
}
int range = (maxi-mini);
if (range < 64){ // si étendue faible -> graphe de 64 points
y_min = (maxi + mini)/ 2 - 31;
y_min = max(0, y_min);
y_max = y_min + 64;
} else { // sinon graphe +20% de l'étendue
y_min = mini - 0.2*range;
y_min = max(0, y_min);
y_max = maxi + 0.2*range;
}
y_max = min(1024, y_max); // on borne à la valeur max du MAX6675
}
void Push(int val){ // Stocke la nouvelle valeur en les décalant toutes
for (int i = 0 ; i<LEN_PLOT ; i++){ // On décale tout
y[i] = y[i+1];
}
y[LEN_PLOT-1] = val; // Et on ajoute la nouvelle valeur
}
void Trace(byte x0, byte x1, byte y0, byte y1){
GLCD.SetPixels(x0, y1, x1, y0, PIXEL_OFF);
for (int i = 0 ; i<LEN_PLOT ; i++){
int u = map(i, 0, LEN_PLOT, x0, x1);
int v = map(y[i], y_min, y_max, y0 , y1) ;
GLCD.SetDot(u ,v ,PIXEL_ON); // On trace les pts du graphe
}
}
};
//----------------------------------------------------------------------------------
// VARIABLES
//----------------------------------------------------------------------------------
gText t[4]; // Affichage des 4 températures
gText curseur; // Curseur graphe courant
gText y[3]; // Etiquettes graphe
Plot p[4]; // 4 graphes de température
unsigned long pm_switch; // Previous millis switch entre graphes
unsigned long pm_refresh; // Previous millis refresh lecture TCs
byte plot_index = 0; // Graphe courant
//----------------------------------------------------------------------------------
// CODE
//----------------------------------------------------------------------------------
double readTC(byte CSpin) { // Lecture MAX6675
uint16_t v;
digitalWrite(CSpin, LOW);
delay(1);
v = shiftIn(MAX6675_SO, MAX6675_SCK, MSBFIRST);
v <<= 8;
v |= shiftIn(MAX6675_SO, MAX6675_SCK, MSBFIRST);
digitalWrite(CSpin, HIGH);
if (v & 0x4) {return NAN;} // Bit 2 = TC déconnecté
v >>= 3; // 3 bits status --> on jette
return v*0.25; // Le reste est le nb de 0.25°C
}
void display_logo(){ // Affichage logo, titre et version
GLCD.DrawBitmap(logo, 15,7);
gText titre;
titre.DefineArea(100,10,15,1,cp437font8x8);
titre.Printf("quadTC");
titre.DefineArea(90,27,30,1,Callibri11);
titre.Printf("by The Grouch'");
titre.DefineArea(100,41,30,1,Callibri11);
titre.Printf("Tooling Co.");
titre.DefineArea(158,57,30,1,Wendy3x5);
titre.Printf(VERSION);
}
void setup() {
pinMode(MAX6675_CS0, OUTPUT);
pinMode(MAX6675_CS1, OUTPUT);
pinMode(MAX6675_CS2, OUTPUT);
pinMode(MAX6675_CS3, OUTPUT);
pinMode(MAX6675_SO, INPUT);
pinMode(MAX6675_SCK, OUTPUT);
GLCD.Init();
display_logo();
readTC(MAX6675_CS0);
readTC(MAX6675_CS1);
readTC(MAX6675_CS2);
readTC(MAX6675_CS3);
delay(2000);
GLCD.ClearScreen();
GLCD.DrawVLine(X0Graph-1,0,64); // Lignes axe Y du graphe
GLCD.DrawHLine(X0Graph-2,0,3);
GLCD.DrawHLine(X0Graph-2,32,3);
GLCD.DrawHLine(X0Graph-2,63,3);
}
void loop() {
unsigned long cm = millis();
if ((cm - pm_refresh) > T_REFRESH){
t[0].DefineArea(2, 3,6,1,cp437font8x8);
t[1].DefineArea(2,20,6,1,cp437font8x8);
t[2].DefineArea(2,37,6,1,cp437font8x8);
t[3].DefineArea(2,54,6,1,cp437font8x8);
int tc = readTC(MAX6675_CS0); // Lecture TC
t[0].Printf("A %4d",tc); // Affichage valeur
p[0].Push(tc); // Stockage valeur pour graphe
tc = readTC(MAX6675_CS1);
t[1].Printf("B %4d",tc);
p[1].Push(tc);
tc = readTC(MAX6675_CS2);
t[2].Printf("C %4d",tc);
p[2].Push(tc);
tc = readTC(MAX6675_CS3);
t[3].Printf("D %4d",tc);
p[3].Push(tc);
y[0].DefineArea(73, 1,4,1,Wendy3x5); // PM plantage avr-gcc si pas fait à chaque loop !?§
y[1].DefineArea(73,58,4,1,Wendy3x5);
y[2].DefineArea(73,30,4,1,Wendy3x5);
y[0].Printf("%4d",p[plot_index].y_max); // Etiquettes de l'axe Y
y[1].Printf("%4d",p[plot_index].y_min);
y[2].Printf("%4d",(p[plot_index].y_min+p[plot_index].y_max)/2);
p[plot_index].AutoScale();
p[plot_index].Trace(X0Graph , 191 , 63, 0);
pm_refresh = cm;
}
if ((cm - pm_switch) > T_SWITCH){ // Lect. potar sélection graphe et affich. curseur
plot_index = map(analogRead(POTAR_PIN)+200, 0, 1023, 0, 3);
curseur.Printf(" "); // On efface le curseur courant
curseur.DefineArea(55,(3+17*plot_index),1,1,cp437font8x8);
curseur.Printf("<"); // Et on affiche le nouveau
pm_switch = cm;
}
}