Nie zaleca się używać zmiennych globalnych bo na Tinkercad nie działają poprawnie.

obraz.png

ARE 2008

/**************************************/
/*      ARE 2008      PTM 2 2024      */
/*      e-mail: [email protected]      */
/*      www   : are.net.pl            */
/**************************************/

#define F_CPU 16000000UL  // 16 MHz
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <stdbool.h> // bool
#include <math.h> // pow()

#define DEBUG 0
#define RS 1 // 1 dane, 0 instrukcje
#define RW 2 // 1 odczytuje, 0 zapisuje
#define E  3 // L -> H -> L, odczytuje dane

void delay_ms(int ms) {
	volatile long unsigned int i;
	for(i=0;i<ms;i++)
		_delay_ms(1);
}
	
void delay_us(int us) {
	volatile long unsigned int i;
	for(i=0;i<us;i++)
		_delay_us(1);
}

void dioda_SET_CV()   { PORTB |=  (1 << PB4); }
void dioda_RESET_CV() { PORTB &= ~(1 << PB4); }

void LCD2x16_init(void) {
  PORTC &= ~(1<<RS); // RS 0 komenda
  PORTC &= ~(1<<RW); // RW 0 zapis

  PORTC |= (1<<E);   // E  1 Rozpoczęcie wprowadzania danych L -> H
  PORTD = 0x38;      // dwie linie, 5x7 punktow       NKB 0011 1000
  PORTC &=~(1<<E);   // E  0 Zakończenie H -> L
  _delay_us(120);

  PORTC |= (1<<E);
  PORTD = 0x0e;      // wlacz wyswietlacz, kursor, miganie
  PORTC &=~(1<<E);
  _delay_us(120);

  PORTC |= (1<<E);
  PORTD = 0x06;     // Nie przesuwaj obrazu
  PORTC &=~(1<<E);
  _delay_us(120);
}

void LCD2x16_clear(void){
  PORTC &= ~(1<<RS); // RS 0
  PORTC &= ~(1<<RW); // RW 0

  PORTC |= (1<<E);
  PORTD = 0x01;      // Czyści wyświetlacz
  PORTC &=~(1<<E);
  delay_ms(120);
}

void LCD2x16_putchar(int data) {
  PORTC |= (1<<RS);  // RS 1 Wpisywanie
  PORTC &= ~(1<<RW); // RW 0     dancyh

  PORTC |= (1<<E);
  PORTD = data;
  PORTC &=~(1<<E);
  _delay_us(120);
}

void LCD2x16_pos(int wiersz, int kolumna) {
  PORTC &= ~(1<<RS); // RS 0
  PORTC &= ~(1<<RW); // RW 0

  PORTC |= (1<<E);
  delay_ms(1);       // 0x80-> Kursor na początek
  PORTD = 0x80+(wiersz-1)*0x40+(kolumna-1);
  delay_ms(1);
  PORTC &=~(1<<E);
  _delay_us(120);
}

Main

int main(void){
  char start[17] = "PTM 2 W_________";
  char data[17]  = "30 X 2024  W____";
  char tmp[16];
  char tmp1[16];
  char tmp2[16];
  
  bool an_proc = false; // analogowy 1, procentowy 0
  unsigned int stop_button = 0;
  unsigned int display_delay = 0;
  unsigned int liczba_petli = 10;
  int i;
  /*          100.00 = 10000 */
  unsigned int SPp   =   500; //  50 % = 0.5
  unsigned int SPc   ;
  unsigned int  Hp   =    40; //   4 % = 0.04
  unsigned int  Hc ;
  unsigned int UPmax =  5000; //   5 V
  unsigned int  Cmax = 40000; // 400 °C
  
  unsigned int SPd   = (unsigned int)round(1024*0.5-1);
  unsigned int  Hd   = (unsigned int)round(1024*0.04-1);
  long int Hd_2 = Hd / 2;
  int  Ed   ;
  //unsigned int PVd   = SPd - Ed; 
  
  //unsigned int PVadc =  
  // unsigned int  Eh   = ? 
  // unsigned int  Ep   = Eh * Hp;
  // unsigned int  Ec   = Ep * Cmax;
  int  Ep;
  int  Ec;

  // unsigned int PVp   = SPp - Ep;
  unsigned int PVp   ;
  // unsigned int PVc   = PVp * Cmax;
  unsigned int PVc   ;
  // unsigned int PVv   = PVp * UPmax;,
  //Ep = SPp - PVp - UPmax;
  unsigned int PV_A0 = 0;

  /* USTAWIENIE PINÓW DO CZYTANIA */
  DDRD = 0xff;
  DDRC = 0xff;
  DDRB = 0xff;
  /* RESETOWANIE WSZYTKICH PINów  */
  // Rejestr odpowiedzialny za ustawianie wartości wyjściowych
  PORTD = 0x00;
  PORTC = 0x00;
  PORTB = 0x00; // RESET
  
  /* PRZESTAWIENIE PINÓW B i PC4 NA TYLKO ODCZYT (guziki) */
  //DDRB = 0x00;       // CZYTANIE B
  //DDRB |= (1 << PB4);// ZAPIS    PIN PB4 {Dioda}
  DDRB =   (1 << PB4); // ZAPIS    PIN PB4 {Dioda} reszta PORTB CZYTANIE
  DDRC &= ~(1 << PC0); // CZYTANIE PIN PC0 {Potencjometr}
  DDRC &= ~(1 << PC4); // CZYTANIE PIN PC4 {Guzik [5] an_proc}
 
   _delay_ms(200);

  LCD2x16_init();
  LCD2x16_clear();

  for(i=0;i < 16;i++) LCD2x16_putchar(start[i]);
  LCD2x16_pos(2,1);
  for(i=0;i < 16;i++) LCD2x16_putchar(data[i]);

  delay_ms(300);
  
  // Ustawienie ADC
  ADMUX = (1 << REFS0) | (0); // Ustaw referencję napięcia na AVcc, wybierz A0
  ADCSRA = (1 << ADEN);       // Włącz ADC
  
  while(1) {
    Ed = SPd - PV_A0;
    /* ========= ODŚWIERZANIE co 0.5 s =========*/
    if (display_delay == liczba_petli && DEBUG) {
      LCD2x16_clear();
      LCD2x16_pos(1,1);
      for(i=0; i<16; ++i) LCD2x16_putchar(tmp1[i]);
      LCD2x16_pos(2,1);
      for(i=0; i<16; ++i) LCD2x16_putchar(tmp2[i]);
      
    } else if (display_delay >= 2*liczba_petli) {
      LCD2x16_clear();
      display_delay = 0;
      // Wyświetl wartość analogową
      if(an_proc) {
        //PVp = (int)round(PV_A0/10.23);
        PVp = (int)(PV_A0/1.023);
        SPp = (int)round((SPd+1)/10.24);
        //sprintf(tmp, "SP=%2d%% PV=%4d%% ",SPp, PVp);
        sprintf(tmp, "SP=%2d%% PV=%2d.%1d%% ",SPp, PVp/10,PVp%10);
      } else {
        PVc = (int)round( (PV_A0/(1023.0))  * Cmax );
        SPc = (int)round( ((SPd+1)/102400.0)* Cmax );
        sprintf(tmp, "SP=%2dC PV=%3d.%1dC",SPc, PVc/100, (PVc%100/10));
      }
      for(i = 0; i < 16; ++i) LCD2x16_putchar(tmp[i]);
      
      LCD2x16_pos(2, 1);
      if(an_proc) {
        //Ep = (int)round( Ed/10.23 );
        Ep = (int)( Ed/1.023 );
        Hp = (int)round((Hd+1)/10.24);
        sprintf(tmp, "H=%2d%%  E=%3d.%1d%%  ",Hp, Ep/10, abs(Ep%10));
        //sprintf(tmp, "H=%2d%%  E=%4d%%  ",Hp, Ep);
        //sprintf(tmp, "%10d  ",Ed);
      } else {
        Ec = (int)round( (Ed/1023.0)  * Cmax );
        Hc = (int)round( ((Hd+1)/102400.0)* Cmax );
        sprintf(tmp, "H=%2dC   E=%3d.%1dC",Hc, Ec/100, abs(Ec%100/10));
      }
      for(i = 0; i < 16; ++i) LCD2x16_putchar(tmp[i]);
    }

    
    if(Ed > Hd_2)       dioda_SET_CV();
    else if(Ed < -Hd_2) dioda_RESET_CV();
    
    /* ========= Odczyt wartości analogowej z A0 ========= */
    ADCSRA |= (1 << ADSC);        // Rozpocznij konwersję
    while (ADCSRA & (1 << ADSC)); // Czekaj na zakończenie konwersji
    PV_A0 = ADC;                  // Zapisz odczytaną wartość z ADC
    
    /* ========= WYKRYWANIE WCIŚNIĘĆ GUZIKÓW ========= */
    if (PINB == 0x0F && DEBUG) {
       sprintf(tmp1,"PINB=0x%02X  DATA=",PINB);
       sprintf(tmp2,"PINC=0x%02X  %s",PINC, an_proc ? "Analg" : "Proc%%");
      
    } else if( !(PINB & (1 << PB0)) ) {
       SPd   = (int)round(1024*0.4-1);      
    } else if( !(PINB & (1 << PB1)) ) {
       SPd   = (int)round(1024*0.6-1);
    } else if( !(PINB & (1 << PB2)) ) {
      	Hd   = (int)round(1024*0.08-1);
        Hd_2 = Hd / 2;
    } else if( !(PINB & (1 << PB3)) ) {
      	Hd   = (int)round(1024*0.1-1);
        Hd_2 = Hd / 2;
    }
    
    if ( !(PINC & (1 << PC4)) && stop_button==0 ) {
      an_proc = !an_proc;
      stop_button = 4*liczba_petli;
    } else if (stop_button > 0) --stop_button;
      
    delay_ms(40);
    ++display_delay;
  }
  
  return 0;
}