Sari la conținut
ELFORUM - Forumul electronistilor

Pagini cu meniu si modificare/salvare parametri


Postări Recomandate

if(!menu_button){
                if(old_menu_button == 0) {
                time_menu_button = millis;
                 old_menu_button = 1;
                 LED1=ON;
                 }
                 }
                 
  else if(old_menu_button) {
         old_menu_button = 0;
	}
}

Domnule Bandi asa se face delay ? ca nu prea inteleg....am facut o variabila in Timer 1 millis, si am facut-o cu ++...nu stiu cum e treaba cu button delay

daca aveti timp faceti-mi si mie un mic exemplu

 

in exemplul acesta nu stiu cum este facut...

	
	if(Button(&PORTC, 5, 1, 0)) {  // buton - pe PORTC - 5 cu debounce de 1ms
	  if (button1_old == 0) {
	    buttonPress(2);
		button_time = millis;
	    button2_old = 1;
	  }
Link spre comentariu

Nu am momentan access la proiectul de unde am scos prima bucata de cod, doar spre seara iin jur de ora 7 cand ajung acasa.

In schimb daca descarci acest mic tool https://libstock.mikroe.com/projects/view/398/timer-calculator care o sa iti genereze codul necesar pentru timer. Eu selectez timer-0 si 1ms, iar apoi in codul generat unde scrie "// put your code here" pun millis++;

 

Acuma cum facem cu millis, este o metoda foarte simpla, salvam intr-o variabila timpul curent dupa care intr-un if verificam cu cat e "millis" mai mare fata de variabila salvata, diferenta intre cele doua este exact cat timp a trecut de la ultima executare a conditiei if in millisecunde.

unsigned long oldTime = 0; //definim o variabila;

if (millis - oldTime > 250) { // atat timp cat millis nu a fost incrementat de 250 de ori nu se executa conditia if ( 250ms)

// definim un cod care sa se execute 1 data la fiecare 250ms

oldTime = millis; // setam oldTime la timpul actual, prin urmare va trebuii ca millis sa se incrementeze de 250 de ori ca confitia sa fie din nou executata
}

Apoi daca in if-ul respectiv includem si verificarea de buton apasat, chiar daca butonul este tinut apasat continu conditia if se va executa doar 1 singura data din cauza conditiei de "millis - oldTime > 250" pentru ca millis trebuie sa se incrementeze de 250 de ori pentru ca conditia sa devina adevarata.

unsigned long oldTime = 0;

if (millis - oldTime > 250 && Button(&PORTC, 5, 1, 0)) { // ambele conditii trebuie sa fie adevarate ca sa se execute if-ul, deci sa treaca si 250ms si sa fie si butonul apasat

// definim un codul

oldTime = millis;
}

In exemplul din libraria Button din MicroC for PIC aveti un exemplu care verifica daca butonul a fost eliberat deci cu metoda acea pentru a incrementa o valoare butonul trebuie apasat - eliberat - apasat - eliberat - etc.. Este practic daca se modifica intervale scurte, daca trebuie incrementate valori de 50-100 e putin neplacut sa apesi si sa eliberezi acel buton de 100 de ori si de acea este mai practic cel cu delay pentru ca poti tine apasat continu butonul iar valoarea este incrementata 1 data la fiecare 250ms sau orice alta temporizare.

 

 

Link spre comentariu

Aveam acel calculator instalat deja de la mars.Dar am timer 1 calculat...

De ce Timer 0 si nu Timer 1?va inteb asta deoarece pe acest controler cu quartz de 4Mhz pe timer 0 am 1,04sec . In librarie este postat butonul insa fara delay.

Mie imi trebuie cu eliberarea butonului, pentru a schimba paginile meniului...deci este necesar codul acela al dvs...am pus un led ca martor , este ok?

void check_menu_button() {
if (millis - old_time_button > 250 && !menu_button){
              old_time_button = millis;
              LED1 = ON;
              }
}
Link spre comentariu

Nu imi schimba pagina :tryre

void check_menu_button() {
int menu = 1;
if (!menu_button && (millis-old_time_button)>500){
              if(old_menu_button == 0){
              switch(menu)
              {
              case 1:
              menu_page1();
              break;
              case 2:
              menu_page2();
              break;
              }
              old_time_button = millis;
              old_menu_button = 1;
                                      } }
              else if(old_menu_button == 1){
              old_menu_button = 0;
              LED2 = OFF;
                                       }

Link spre comentariu

Pin-ul de enable este controlat de librarie nu trebuie facut nimic manual. Folosesc timer 0 pentru ca timer 1 este de 16 biti (precizie mai maire) si nu vreau sa-l tin ocupat pentru un simplu counter de timp. Nu stiu exact la modelul acesta de PIC dar timer 1 scoate 1ms lejer pe 4Mhz, eu il folosesc si la 250uS fara probleme. Daca setezi in acel programel PIC16, 4Mhz, 1ms trebuie sa iti genereze codul pentru fix 1ms. Daca la teste iti iese mai mult de 1ms atunci sunt probabil problem la configurarea projectului.

 

Pune cod-ul intreg in acel if ai "!menu_button" dar nu reiese unde anume ii dai valoarea, ma gandesc ca undeva ii da valoarea portului pe care ai butonul.

Link spre comentariu

#include "hw_LCD_init.h"

#define LED_AV_dir TRISB2_bit //Output for Emergency status (RED LED)
#define LED_AV PORTB.F2

#define LED1_dir TRISB4_bit //Output for LED1
#define LED1 PORTB.F4
#define LED2_dir TRISB5_bit //Output for LED2
#define LED2 PORTB.F5

#define display_light_dir TRISC1_bit //Output for display light dimm
#define display_light PORTC.F1

#define down_button_dir TRISB0_bit //Input Down_Button(decrease)
#define down_button PORTB.F0

#define up_button_dir TRISC7_bit //Input Up_Button(increase)
#define up_button PORTC.F7

#define menu_button_dir TRISC5_bit //Input Menu_Button
#define menu_button PORTC.F5

#define enter_button_dir TRISC4_bit //Input Enter_Button(OK)
#define enter_button PORTC.F4

#define fwd_relay_dir TRISC6_bit //Output for forward sense
#define fwd_relay PORTC.F6

#define rew_relay_dir TRISB1_bit //Output for rewind sense
#define rew_relay PORTB.F1

#define INPUT 1U
#define OUTPUT 0U

// anonymous enumeration to store possible states of the outputs
enum {
ON = 1,
OFF = 0 };

volatile unsigned long millis = 0;
unsigned long old_time_button = 0; //variabila pentru memorarea starii butonului
unsigned long old_time_display = 0;
unsigned int old_menu_button = 0,old_enter_button = 0 ;
unsigned int submenu;


void hw_init()
{


LED_AV_dir = OUTPUT;
LED_AV = OFF;

LED1_dir = OUTPUT;
LED1 = OFF;

LED2_dir = OUTPUT;
LED2 = OFF;

down_button_dir = INPUT;
up_button_dir = INPUT;
menu_button_dir = INPUT;
enter_button_dir = INPUT;

display_light_dir = OUTPUT;
display_light = OFF;

fwd_relay_dir = OUTPUT;
fwd_relay_dir = OFF;

rew_relay_dir = OUTPUT;
rew_relay_dir = OFF;


}

//Timer1
//Prescaler 1:1; TMR1 Preload = 64536; Actual Interrupt Time : 1 ms

void InitTimer1(){
T1CON = 0x01;
TMR1IF_bit = 0;
TMR1H = 0xFC;
TMR1L = 0x18;
TMR1IE_bit = 1;
INTCON = 0xC0;
}

void Interrupt(){
if (TMR1IF_bit){
TMR1IF_bit = 0;
TMR1H = 0xFC;
TMR1L = 0x18;
millis++;
}
}

void start_page(){
Lcd_Out(1, 1, " CONTROL ");
Lcd_Out(2, 1, " MOTOR CC ");
delay_ms(2000);
Lcd_Out(1, 1, "Sens: PWM= %");
Lcd_Out(2, 1, "U= V I= mA");
}

unsigned int menu = 0;
void check_menu_button() {
//pagini meniu
if (!menu_button && (millis-old_time_button)>250){
if(old_menu_button == 0){
menu++;
}
switch(menu){
case 1:
submenu = 0;
Lcd_Out(1, 1, " MENIU ");
Lcd_Out(2, 1,">Setari generale");
break;
case 2:
Lcd_Out(1, 1, " MENIU ");
Lcd_Out(2, 1,"> Setari motor ");
submenu = 1;
break;
case 3:
Lcd_Out(1, 1," MENIU ");
Lcd_Out(2, 1,"> Set mod start ");
submenu = 2;
menu = 0;
break;
}
old_time_button = millis;
old_menu_button = 1;
}
else if(old_menu_button == 1){
old_menu_button = 0;
}

}

void submenu_page(){
if(!enter_button && (millis-old_time_button)>500){
if(submenu == 0 && old_enter_button == 0){
Lcd_Out(1, 1, "Setari generale");
Lcd_Out(2, 1, " ILL= % ");
menu = 0;
}
old_time_button = millis;
old_enter_button = 1;
}
else if(old_enter_button == 1){
old_enter_button = 0;
}
}


void main(){
ADCON1 =0x04; //All analog pins are digital(without RA0, RA1 and RA3)

LCD_Init();
LCD_CMD(_LCD_CURSOR_OFF);
LCD_CMD(_LCD_CLEAR);

InitTimer1();
hw_init();
display_light = ON;
start_page();
//show_lcd();
while(1){

check_menu_button();
submenu_page();

} }

Link spre comentariu

Nu vad unde ar putea sa fie problema, la prima vedere pare ok partea de butoane. Eu as sugera sa instalezi Proteus daca inca nu il ai ca sa poti face simulari, sa faci un proiect nou si sa incerci un simplu toggle la un LED cu metoda respectiva de buton si sa vezi daca merge sau nu. Daca nu ii dai de cap o sa ma uit eu in seara asta, e cam aliniat aiurea codul si imi e foarte greu sa-l descifrez, o sa-l pun intrun proiect MikroC si sa vad in simulare cam ce se intampla exact.

Link spre comentariu

Salut,

 

Subscriu, formatarea este groaznica.

Ti-am rescris functia check_menu_button(), verifica daca iti merge cel putin partea de trecere prin meniul principal.

Comenteaza in bucla principala cealalta functie, cea cu submenu pentru ca sa te asiguri ca totul este OK asa.

void check_menu_button() {
  static unsigned char menu = 1;
  
  if (menu_button) old_menu_button = 1; //daca butonul este neapasat, memoreaza starea acestuia in old_menu_button
  else {
    old_menu_button = 0;                //altfel, butonul e apasat, memoreaza starea curenta
    old_time_button = millis;           //initializeaza variabila timer: old_time_button
  }
  
  //pagini meniu
  //daca starea anterioara a butonului este apasata si au trecut 10 milisecunde de atunci
  //deci s-a terminat cu bouncing-ul
  if (!old_menu_button && ((millis - old_time_button) > 10)){
    //daca butonul este inca apasat atunci
    if (!menu_button){
      if (menu == 4) menu = 1;
      else menu++;                      //treci la urmatorul meniu
    }
  }

  switch(menu){
      case 1:
        Lcd_Out(1, 1, "      MENIU     ");
        Lcd_Out(2, 1, ">Setari generale");
        submenu = 0;
        break;
      case 2:
        Lcd_Out(1, 1, "      MENIU     ");
        Lcd_Out(2, 1, "> Setari motor  ");
        submenu = 1;
        break;
      case 3:
        Lcd_Out(1, 1, "      MENIU     ");
        Lcd_Out(2, 1,"> Set mod start ");
        submenu = 2;
        break;
  }
}

LE: nu e buna varianta de mai sus, o sa treaca ca racheta prin meniu-uri, va trebui refacuta functia ...

 

LLE: pana una alta incearca varianta clasica cu delay_ms():

void check_menu_button() {
  static unsigned int menu = 1;

  if (menu_button) old_menu_button = 1; //daca butonul este neapasat, memoreaza starea acestuia in old_menu_button

  //pagini meniu
  //daca butonul este apasat si starea anterioara a butonului este apasata si au trecut 10 milisecunde de atunci
  //deci s-a terminat cu bouncing-ul
  if (!menu_button && old_menu_button){
    //daca butonul este tot apasat atunci
    delay_ms(10);
    if (!menu_button){
      if (menu == 4) menu = 1;
      else menu++;               //treci la urmatorul meniu
      old_menu_button = 0;
    }
  }

  switch(menu){
      case 1:
        Lcd_Out(1, 1, "      MENIU     ");
        Lcd_Out(2, 1, ">Setari generale");
        submenu = 0;
        break;
      case 2:
        Lcd_Out(1, 1, "      MENIU     ");
        Lcd_Out(2, 1, "> Setari motor  ");
        submenu = 1;
        break;
      case 3:
        Lcd_Out(1, 1, "      MENIU     ");
        Lcd_Out(2, 1,"> Set mod start ");
        submenu = 2;
        break;
  }
}
Editat de mars01
Link spre comentariu

Sper ca asa sa iti mearga si trecerea in meniuri sa se faca pe tranzitia de la HIGH la LOW:

void check_menu_button() {
  static unsigned char menu = 1;       //la pornire se afiseaza automat primul meniu
  static unsigned int  time_start = 0;

  if (menu_button) old_menu_button = 1; //daca butonul este neapasat, memoreaza starea acestuia in old_menu_button

  //daca butonul este apasat si starea anterioara a butonului este neapasata incepe temporizarea
  //asteptand sa se termine cu bouncing-ul, adica aprox 10ms
  if (!menu_button && old_menu_button){
    time_start = millis;
    old_menu_button = 0;
  }
  
  //daca butonul este apasat si bouncing-ul a trecut (au trecut 10ms)
  //atunci se poate spune cu siguranta ca butonul este apasat
  if (!menu_button && (millis - time_start) > 10)){
    if (menu == 4) menu = 1;   //daca meniul a ajuns la capat, sa revina la inceput
    else menu++;               //treci la urmatorul meniu
  }

  switch(menu){
      case 1:
        Lcd_Out(1, 1, "      MENIU     ");
        Lcd_Out(2, 1, ">Setari generale");
        submenu = 0;
        break;
      case 2:
        Lcd_Out(1, 1, "      MENIU     ");
        Lcd_Out(2, 1, "> Setari motor  ");
        submenu = 1;
        break;
      case 3:
        Lcd_Out(1, 1, "      MENIU     ");
        Lcd_Out(2, 1,"> Set mod start ");
        submenu = 2;
        break;
  }
}
Link spre comentariu

Nu prea ma inteleg cu formatarea...o sa ma uit la tutoriale...in legatura cu Proteus-ul il am,insa pe simulare sunt sigur ca va merge normal...am facut pe cel cu termostatul si flash-ul era setata la 500ms si Proteus il facea la 2 secunde....in fine...

La program nu am mai lucrat, am incercat sa pornesc ADC-ul si display-ul face ca toate visele, cred ca trebuia sa fac toate porturile B pe display, adica nu folosesc cu A....o sa modific pe viitor placa...

Sarbatori Fericite!!!!

Link spre comentariu

Daca e configurat totul corect Proteus trebuie sa simuleze corect, daca in loc de 500ms iti dadea 2s atunci inseamna ori ca la configurari (unde ai ales hex-ul) nu era setat corect frecventa de lucru ori in MikroC nu e setat corect in project settings frecventa. Daca e corect si aceiasi frecventa in ambele locuri atunci incearca sa setezi manual, vezi prin Datasheet cum se face, de obicei e OSCCON. Am mai patit si eu ca in proteus selectam o frecventa anume si cand am pus in practica imi dadea total diferit si dupa acea am descoperit ca in anumite cazuri MikroC nu seteaza corect registrul OSCCON si de atunci eu il setez de fiecare data manual sa fiu sigur ca e valoarea corecta.

Editat de Bandi Szasz
Link spre comentariu

M-am uitat prin datasheet si PIC16F876A nu are osccilator intern din pacate. In cazul acesta trebuie unu-l extern, sa va uitati pe circuit ce osccilator are, probabil unu-l de 20Mhz. In simulare puneti un quartz de xMhz pe pinii notati OSC1 / OSC2 ( sunt pinii 9 / 10 ) si in fereastra de meniu unde ati ales si hex-ul pentru PIC puneti aceasi valoare. In MikroC la fel in "project settings" sa fie trecut aceasi frecventa si copiati valorile autogenerate CONFIG in setarile PIC-ului din proteus.

Editat de Bandi Szasz
Link spre comentariu

Creează un cont sau autentifică-te pentru a adăuga comentariu

Trebuie să fi un membru pentru a putea lăsa un comentariu.

Creează un cont

Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!

Înregistrează un nou cont

Autentificare

Ai deja un cont? Autentifică-te aici.

Autentifică-te acum
×
×
  • Creează nouă...

Informații Importante

Am plasat cookie-uri pe dispozitivul tău pentru a îmbunătății navigarea pe acest site. Poți modifica setările cookie, altfel considerăm că ești de acord să continui.Termeni de Utilizare si Ghidări