Climatizador Practica

Hola compañeros, no soy muy especializado en el tema y estoy "aprendiendo" en clase... pues el programa que tengo que hacer es el siguiente:

Construir un termostato de un climatizador invierno verano. El led trece estará encendido en invierno cuando la temperatura sea inferior a la deseada y encendido en verano cuando la temperatura sea superior a la deseada. La temperatura se visualizara en un display de cuádruple de 7 segmentos. Se incrementara y se decrementará por la pulsación del dos pulsadores al levantar el botón. La conmutación invierno/verano la hará un tercer pulsador. La primera cifra del display mostrará: H en invierno y C en varano. Implementarlo con el LM35.

Mi codigo hasta ahora y aqui quedo bloqueado es el siguiente:

int SevenSegment [13][7]={  {1,1,1,1,1,1,0}, //0
                            {0,1,1,0,0,0,0}, //1
                            {1,1,0,1,1,0,1}, //2
                            {1,1,1,1,0,0,1}, //3
                            {0,1,1,0,0,1,1}, //4
                            {1,0,1,1,0,1,1}, //5
                            {1,0,1,1,1,1,1}, //6
                            {1,1,1,0,0,0,0}, //7 
                            {1,1,1,1,1,1,1}, //8
                            {1,1,1,1,0,1,1}, //9
                            {1,0,0,1,1,1,0}, //C
                            {0,1,1,0,1,1,1}, //H
                            {0,0,0,0,0,0,0}};//Blank

int PinLed[7] = {38,40,42,44,46,48,50};
int LedPunto = 52;

int Display[4] = {22,24,26,28};

int BotSubir = 19;    //Interrupcion 4
int BotBajar = 20;    //Interrupcion 3
int BotEstacion = 21; //Interrupcion 2

void setup() 
{
  for(int i=0;i<8;i++)
    {pinMode (PinLed[i],OUTPUT);}
  
  for (int i=0;i<5;i++)
    {pinMode (Display[i], OUTPUT);}

  pinMode (LedPunto,OUTPUT);

  pinMode(BotSubir, INPUT_PULLUP);
  pinMode(BotBajar, INPUT_PULLUP);
  pinMode(BotEstacion, INPUT_PULLUP);

  attachInterrupt(4, Subir, RISING);
  attachInterrupt(3, Bajar, RISING);
  attachInterrupt(2, Estacion, RISING);
  Serial.begin(9600);
  
}

void loop() 
{
  int lm = analogRead(A0);
  double temp = (5.0 * lm * 100.0)/1024.0;
  Serial.print(temp);
  Serial.println(" Grados Centigrados");
  delay(0);
  
}

void Subir(){}

void Bajar(){}

void Estacion(){}

Haber si pudieseis hecharme una mano, mas que nada para entenderlo. Gracias anticipadas

Hola Carlitos1991, bienvenido al foro.
No se si tu tarea debe hacerse sin el uso de librerías.
En lo personal esta librería Sevseg simplifica todo lo que tu deseas hacer.

Mira que fácil es

#include "SevSeg.h"

SevSeg sevseg; //Instantiate a seven segment controller object

void setup() {
  byte numDigits = 4;   
  byte digitPins[] = {2, 3, 4, 5}; // lo cambias a gusto
  byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13}; // lo cambias a gusto

  sevseg.begin(COMMON_ANODE, numDigits, digitPins, segmentPins); // defines el tipo de display 7 segmentos
  sevseg.setBrightness(90); // controlas el brillo
}

void loop() {
  static unsigned long timer = millis();
  static int deciSeconds = 0;
  
  if (millis() >= timer) {
    deciSeconds++; // 100 milliSeconds is equal to 1 deciSecond
    timer += 100; 
    if (deciSeconds == 10000) { // Reset to 0 after counting for 1000 seconds.
      deciSeconds=0;
    }
    sevseg.setNumber(deciSeconds, 1);
  }

  sevseg.refreshDisplay(); // Must run repeatedly
}

Otra cosa que no esta mal pero no me parece necesario es usar interrupciones para controlar los botones.
No hace falta.
Simples rutinas de scaneo alcanzan para controlar los pulsadores UP, DOWN, etc. mientras no uses delay.
En su defecto si necesitas controlar tiempo aprende a usar millis();

surbyte:
Hola Carlitos1991, bienvenido al foro.
No se si tu tarea debe hacerse sin el uso de librerías.
En lo personal esta librería Sevseg simplifica todo lo que tu deseas hacer.

Mira que fácil es

#include "SevSeg.h"

SevSeg sevseg; //Instantiate a seven segment controller object

void setup() {
  byte numDigits = 4; 
  byte digitPins[] = {2, 3, 4, 5}; // lo cambias a gusto
  byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13}; // lo cambias a gusto

sevseg.begin(COMMON_ANODE, numDigits, digitPins, segmentPins); // defines el tipo de display 7 segmentos
  sevseg.setBrightness(90); // controlas el brillo
}

void loop() {
  static unsigned long timer = millis();
  static int deciSeconds = 0;
 
  if (millis() >= timer) {
    deciSeconds++; // 100 milliSeconds is equal to 1 deciSecond
    timer += 100;
    if (deciSeconds == 10000) { // Reset to 0 after counting for 1000 seconds.
      deciSeconds=0;
    }
    sevseg.setNumber(deciSeconds, 1);
  }

sevseg.refreshDisplay(); // Must run repeatedly
}




Otra cosa que no esta mal pero no me parece necesario es usar interrupciones para controlar los botones.
No hace falta.
Simples rutinas de scaneo alcanzan para controlar los pulsadores UP, DOWN, etc. mientras no uses delay.
En su defecto si necesitas controlar tiempo aprende a usar millis();

Anda, pues alomejor el profesor no sabe la existencia de esa libreria o nos lo ha hecho mas laborioso... asi que tengo que hacerlo asi suelto... como lo llevo y con las interrupciones que es lo que estamos practicando ahora jajajaja. Me guardo el codigo para preguntarle que si asi tambien valdria. Mil gracias y haber si puedes seguir ayudandome, aun asi si conoces un canal de videos o lectura recomendada de programacion si puedes asesorarme te lo agradezco, una vez tube la ocasion de tener arduino a fondo (Libro) y lo que necesite me ayudo bastante. De nuevo muchas gracias compañero

Ve al foro Documentación, ahora estas en Software y mira las clases 0 a 7 y de 8 en adelante que son todas de Youtube y te van a ayudar mucho.

surbyte:
Ve al foro Documentación, ahora estas en Software y mira las clases 0 a 7 y de 8 en adelante que son todas de Youtube y te van a ayudar mucho.

Esas las mire para un examen, volvere a hecharles un vistazo haber que saco, lo que vaya consiguiendo luego lo pondre por aqui por si alguien se encuentra en la necesidad de realizar lo mismo

Bueno si debes seguir con tu código tal como lo tienes, dime que te falta?

surbyte:
Bueno si debes seguir con tu código tal como lo tienes, dime que te falta?

Mira compañero Surbyte, este codigo es de un compañero de clase, pues tengo que hacer algo asi. Pero la cosa es que lo del void loop no lo comprendo, y por mi propio metodo de pensar como puedo sacarlo... pues no llego a imaginar como se hace. Si puedes explicame las lineas de esa parte haber si consigo entenderlo y apartir de ahi crear algo yo, aunque me equivoque, lo que quiero es aprender :wink:

int SevenSegment [][7]={{1,1,1,1,1,1,0}, //0
                          {0,1,1,0,0,0,0}, //1
                          {1,1,0,1,1,0,1}, //2
                          {1,1,1,1,0,0,1}, //3
                          {0,1,1,0,0,1,1}, //4
                          {1,0,1,1,0,1,1}, //5
                          {1,0,1,1,1,1,1}, //6
                          {1,1,1,0,0,0,0}, //7 
                          {1,1,1,1,1,1,1}, //8
                          {1,1,1,1,0,1,1}, //9
                          {1,0,0,1,1,1,0}, //C
                          {0,1,1,0,1,1,1}, //H
                          {0,0,0,0,0,0,0}};//Blank
int Led[7] = {40, 32, 37, 41, 43, 38, 35};
int LedP = 13;
int Dig[4] = {42, 36, 34, 33};
int BotS = 21;
int BotB = 20;
int BotE = 19;
int i,j,b=1;
volatile int est=0, s = 60;
int m=10;
int Display[4]={12,22,2,0};
int tn, tv=0;
int temp=18;                       

void setup() 
{
  #ifdef DEBUG
  Serial.begin(9600);
  #endif
  for(i=0; i<8; i++)
  {
    pinMode(Led[i], OUTPUT);
  }
  pinMode(LedP, OUTPUT);
  for(i=0; i<4; i++)
  {
    pinMode(Dig[i], OUTPUT);
  }

  pinMode(BotS, INPUT_PULLUP);
  pinMode(BotB, INPUT_PULLUP);
  pinMode(BotE, INPUT_PULLUP);


  attachInterrupt(2, tempmas, FALLING);
  attachInterrupt(3, tempmenos, FALLING);
  attachInterrupt(4, estacion, FALLING);

}

void loop() 
{
   tn=millis();
   if ((tn-tv)<10000) LeeTemp();
//ajustes de las cifras a mostrar
    if(est==0) Display[2]=12;
    else  Display[2]=16;
    //Display[3]=22;
    Display[0]=temp/10;
    Display[1]=temp%10;
    for(i=0; i<4; i++)
    {
      #ifdef DEBUG
      Serial.println(Display[i]);
      #endif
            delay(1);
      digitalWrite(Dig[i],LOW);
      
      for(j=0; j<7; j++)
      {
        digitalWrite(Led[j],SevenSegment[Display[i]][j]);

      }
      delay(5);
      digitalWrite(Dig[i],HIGH);

    }
}

void tempmas()
{
  if(temp<26)temp++;
}
void tempmenos()
{
  if(temp>16)temp--;
}
void estacion()
{
  est=!est;
}

void LeeTemp()
{
   int t = analogRead(A0); 
   temp = (5.0 * t * 100.0)/1024.0;  
}

Gracias por todo

Waste of memory. Try this, just 12 bytes:

byte SevenSegment []={
0b01111110, // 1,1,1,1,1,1,0}, //0
0b00110000, // 0,1,1,0,0,0,0}, //1
0b01101101, // 1,1,0,1,1,0,1}, //2
0b01111001, // 1,1,1,1,0,0,1}, //3
0b00110011, // 0,1,1,0,0,1,1}, //4
0b01011011, // 1,0,1,1,0,1,1}, //5
0b01011111, //1,0,1,1,1,1,1}, //6
0b01110000, // 1,1,1,0,0,0,0}, //7 
0b01111111, // 1,1,1,1,1,1,1}, //8
0b01111011, // 1,1,1,1,0,1,1}, //9
0b01001110, // 1,0,0,1,1,1,0}, //C
0b00110111, // 1,1,0,1,1,1}, //H
0b00000000, // 0,0,0,0,0,0,0,//Blank
};

Para comenzar lo que te sugiere CrossRoads es parte de lo que te iba a decir.

 tn=millis();

millis() es una función que devuelve el tiempo en milisegundos desde que enciendes el arduino. Siempre se incrementa en 1 mseg. Los valores son del tipo unsigned long o sea 2^32 -1 bits = 4.294.967.295 mseg

   if ((tn-tv)<10000) LeeTemp();

tn lo carga con el valor de millis() asi que imagina que es un cronómetro que se puso en marcha.
Tomas el valor tn en un momento del comienzo del loop okay?
tv tiene otro valor que en algun momento también lo inicializaste con un momento de millis().
Su resta mientras sea menor que 10000 mseg o sea 10*1000 mseg = 10 seg ejecutará LeeTemp()
A mi esta parte no me gusta pero luego lo vemos.

//ajustes de las cifras a mostrar
    if(est==0) Display[2]=12;
    else  Display[2]=16;
    //Display[3]=22;

Aca fija unos valores.. no entiendo para que?

    Display[0]=temp/10;
    Display[1]=temp%10;

el valor de temp lo descompone en unidades y decenas para poder ser mostrado en display 0 y 1[/color]

    for(i=0; i<4; i++)
    {
      #ifdef DEBUG
      Serial.println(Display[i]);
      #endif
            delay(1);
      digitalWrite(Dig[i],LOW);
      
      for(j=0; j<7; j++)
      {
        digitalWrite(Led[j],SevenSegment[Display[i]][j]);

      }
      delay(5);
      digitalWrite(Dig[i],HIGH);

    }
}

Con esta parte del programa, se encarga de mostrar el contenido almacenado de cada display, habilitando el que corresponda usando digitalWrite(Dig*,HIGH);*
Luego vienen las rutinas de interrupción
* *void tempmas() {   if(temp<26)temp++; }* *
Esto permite subir el termostato hasta 25 grados
```
*void tempmenos() {

if(temp>16)temp--;
}*
* *Esta baja la temp del termostato siempre que sea mayor que 16* *
void estacion() {
  est=!est;
}

* *cambia el estado de est.* *Cada vez que presionas el pin correspondiente, est toma el valor opuesto al que tenía.* *Si vale 1 la operación !est dice niega el valor de est, o sea inviertelo.* *!1 = 0* *!0 = 1* *
void LeeTemp()
{
  int t = analogRead(A0);
  temp = (5.0 * t * 100.0)/1024.0; 
}

```
aca se lee el valor del sensor de temperatura pero hay un error. Se divide por 1023 ya que el AD del arduino es de 10 bits y 10 bits = 2^10=1024 ahhh 1024 pero los valores que entrega son de 0 a 1023 que si los cuentas son 1024.
Entonces... imagina que el ad devuelve el máximo que es justamente 1023
si tu divides 1023/1024 cuanto te da en float? pues mas de 1 y cuanto es mas de 1.X x 5.0 = mas de 5.0 Volts
Y con que alimentas el Arduino? Con 5V por ende, nopuedes superar los 5V que te entrega no?
Es un error muy común.
Espero te sirva la explicación.

surbyte:
Para comenzar lo que te sugiere CrossRoads es parte de lo que te iba a decir.

 tn=millis();

millis() es una función que devuelve el tiempo en milisegundos desde que enciendes el arduino. Siempre se incrementa en 1 mseg. Los valores son del tipo unsigned long o sea 2^32 -1 bits = 4.294.967.295 mseg

   if ((tn-tv)<10000) LeeTemp();

tn lo carga con el valor de millis() asi que imagina que es un cronómetro que se puso en marcha.
Tomas el valor tn en un momento del comienzo del loop okay?
tv tiene otro valor que en algun momento también lo inicializaste con un momento de millis().
Su resta mientras sea menor que 10000 mseg o sea 10*1000 mseg = 10 seg ejecutará LeeTemp()
A mi esta parte no me gusta pero luego lo vemos.

//ajustes de las cifras a mostrar

if(est==0) Display[2]=12;
    else  Display[2]=16;
    //Display[3]=22;







Aca fija unos valores.. no entiendo para que?






Display[0]=temp/10;
    Display[1]=temp%10;




el valor de temp lo descompone en unidades y decenas para poder ser mostrado en display 0 y 1[/color]




for(i=0; i<4; i++)
    {
      #ifdef DEBUG
      Serial.println(Display[i]);
      #endif
            delay(1);
      digitalWrite(Dig[i],LOW);
     
      for(j=0; j<7; j++)
      {
        digitalWrite(Led[j],SevenSegment[Display[i]][j]);

}
      delay(5);
      digitalWrite(Dig[i],HIGH);

}
}




Con esta parte del programa, se encarga de mostrar el contenido almacenado de cada display, habilitando el que corresponda usando digitalWrite(Dig*,HIGH);*
*Luego vienen las rutinas de interrupción*
*```*
*void tempmas()

{
  if(temp<26)temp++;
}*

* *Esto permite subir el termostato hasta 25 grados* *
*void tempmenos() {

if(temp>16)temp--;
}*

* *Esta baja la temp del termostato siempre que sea mayor que 16* *
void estacion() {
  est=!est;
}

* *cambia el estado de est.* *Cada vez que presionas el pin correspondiente, est toma el valor opuesto al que tenía.* *Si vale 1 la operación !est dice niega el valor de est, o sea inviertelo.* *!1 = 0* *!0 = 1* *
void LeeTemp()
{
  int t = analogRead(A0);
  temp = (5.0 * t * 100.0)/1024.0; 
}

```
aca se lee el valor del sensor de temperatura pero hay un error. Se divide por 1023 ya que el AD del arduino es de 10 bits y 10 bits = 2^10=1024 ahhh 1024 pero los valores que entrega son de 0 a 1023 que si los cuentas son 1024.
Entonces... imagina que el ad devuelve el máximo que es justamente 1023
si tu divides 1023/1024 cuanto te da en float? pues mas de 1 y cuanto es mas de 1.X x 5.0 = mas de 5.0 Volts
Y con que alimentas el Arduino? Con 5V por ende, nopuedes superar los 5V que te entrega no?
Es un error muy común.
Espero te sirva la explicación.
[/quote]
Gracias por el trabajo de la explicacion compañero. Como ya imaginaras se trata de un display de 7 segmentos cuadruple. En las dos cifras de la derecha he de mostrar la temperatura como bien has explicado, en la 3 cifra empezando desde la derecha el hueco solo y en la cuarta cifra desde la derecha C de cool o H de Heat, unicamente trato de conseguir eso, pero tengo muy poca idea jajajja. Voy a intentarlo y te pongo mis dudas si no funcionase. Gracias y Saludos

No empieces con todo.
Empieza con mostrar algo en 1 display. Luego que lo comprendas sigues con dos y luego con lo que gustes.
Si copias y pegas no aprendes nada.

surbyte:
No empieces con todo.
Empieza con mostrar algo en 1 display. Luego que lo comprendas sigues con dos y luego con lo que gustes.
Si copias y pegas no aprendes nada.

Compañero, he llegado aqui, haber si apartir de esto poco que he hecho me das unas pautas

#define DEBUG

int SevenSegment [10][7] = {  {1,1,1,1,1,1,0}, //0
                              {0,1,1,0,0,0,0}, //1
                              {1,1,0,1,1,0,1}, //2
                              {1,1,1,1,0,0,1}, //3
                              {0,1,1,0,0,1,1}, //4
                              {1,0,1,1,0,1,1}, //5
                              {1,0,1,1,1,1,1}, //6
                              {1,1,1,0,0,0,0}, //7 
                              {1,1,1,1,1,1,1}, //8
                              {1,1,1,1,0,1,1}, //9
                            };

int cool_heat [2][7] = { {1,0,0,1,1,1,0}, //C
                         {0,1,1,0,1,1,1}  //H
                       };

int PinLed[7] = {38,40,42,44,46,48,50};
int LedPunto = 52;

int Display[4] = {22,24,26,28};

int BotSubir = 19;    //Interrupcion 4
int BotBajar = 20;    //Interrupcion 3
int BotEstacion = 21; //Interrupcion 2

int tnuevo, tviejo = 0;
int temp;
volatile int estacion = 0;

void setup() 
{
  for(int i=0;i<8;i++)
    {pinMode (PinLed[i],OUTPUT);}
  
  for (int i=0;i<5;i++)
    {pinMode (Display[i], OUTPUT);}

  pinMode (LedPunto,OUTPUT);

  pinMode(BotSubir, INPUT_PULLUP);
  pinMode(BotBajar, INPUT_PULLUP);
  pinMode(BotEstacion, INPUT_PULLUP);

  attachInterrupt(4, Subir, FALLING);
  attachInterrupt(3, Bajar, FALLING);
  attachInterrupt(2, Estacion, FALLING);
  Serial.begin(9600);
  
}

void loop() 
{ 
  tnuevo=millis();
  if((tnuevo-tviejo)<10000)
  {
    int lm = analogRead(A0);
    temp = (5.0 * lm * 100.0)/1023.0;
    
    //Prueba Visualizacion Temperatura
    Serial.print(temp);
    Serial.println(" Grados Centigrados");
    delay(50);
  }

  //Colocacion de temperatura en display y de la estacion
  Display [2]= temp/10;
  Display [3]= temp%10;
  
  //if (estacion == 0) Display[] // con esto pretendo cinfigurar el cambio de estacion con cool_heat
  //else 
  
  for (int i=0;i<5;i++)
  { digitalWrite (Display[i],LOW);
    for (int j=0;j<7;j++)
    {
      digitalWrite (PinLed[j],SevenSegment[i][j]);
    }delay(5);
    digitalWrite (Display[i],HIGH);
  }
}
void Subir(){if(temp<26)temp++;}

void Bajar(){if(temp>16)temp--;}

void Estacion(){}// lo dejo para el cambio de estacion

He conseguido dejar uno apagado y me he aclarado el orden de los display probando de uno en uno de manera que el que se tiene que quedar apagado es el 2. Una duda que me surge es la utilizacion de los millis() osea el conteo ese para que se utiliza?? Voy a Seguir trabajando en ello. Gracias