Newsgroup: it.hobby.elettronica.digitale
Titolo: programma Mikrobasic

salve a tutti
come al solito provo a fare le cose ma poi mi blocco su qualche bischerata 
:-(((
ho fatto un programma in Mikrobasic che mi dovrebbe funzionare da contagiri 
per un tornio ed in più mi dovrebbe regolare la velocità della macchina 
attraverso un inverter, comandato in tensione 0-10V, creata dal PWM del pic.
un piccolo PID molto grezzo
la parte acquisizione dati funziona (interrupt RB0)
la parte pwm funziona  e la tensione varia per i valori indicati (grazie 
Simone Bern)
i display visualizzano ma non mi riesce avere una lettura stabile e certa 
dei giri, i numeri oscillano continuamente e mi sembra che non siano 
coerenti con il valore dei giri reali (visualizza da 3 a 5 cifre) il tornio 
è piccolo ed al massimo arriva a fare 1500 giri/min (25Hz)
il sistema che ho pensato è quello di far partire il TIMER1 con l'impulso 
del CAPTURE, fronte di salita, sul piedino RC1 (RC2 viene usato dal PWM del 
Mikrobasic) e tutte le volte che ottenevo un overflow del timer1 andavo ad 
incrementare una variabile (PERIODO1) al momento dell'arrivo dell'altro 
fronte di salita, periodo1 viene trasferito in un altre variabile di 
appoggio, sommata ai valori di CCPR2L e di CCPR2H ed eseguito il calcolo per 
arrivare direttamente al numero dei giri (120000000/periodo)...
cosa sto sbagliando???
ciao
Roberto
program tornioPIC
'pic16f876 @ 8MHz
'lo scopo di questo programma è di contare i giri di un tornio
'e creare un PID che stabilizzi il numero dei giri il
'più vicino possibile al valore impostato nella variabile DATO
dim dato,olddato,girim,compensa as byte
dim giri, oldgiri, giri2,oldgiri2,periodo1,period as word
dim periodo as longint
dim txt as string[5]
sub procedure interrupt
  if TestBit(INTCON,INTF) = 1 then          'RB0
     if portb.1 = 0 then                                  'RB1
        if dato>=255 then
           dato=255
        else
            dato=dato+1
        end if
     else
        if dato<=0 then
            dato=0
        else
            dato=dato-1
        end if
     end if
     compensa=dato
     ClearBit(INTCON,INTF)
  end if
  if TestBit(PIR2,CCP2IF) = 1 then        'RC1  se rc1 va alto
      TMR1L     =0
      TMR1H     =0
      period    =periodo1
      periodo1  =0
      ClearBit(PIR2,CCP2IF)
  end if
  if TestBit(PIR1,TMR1IF) = 1 then        'overflow timer1
      inc(periodo1)                                    'che avviene ogni 
0.0327675 secondi
      ClearBit(PIR1,TMR1IF)                   '(2000000/65535)
  end if
end sub
main:
  trisa   = %000000
  trisb   = %11111111
  trisc   = %11111111
  adcon1 = %00000111
  OPTION_REG.INTEDG=1             ' Interrupt on rising edge on RB0
  INTCON.GIE  = 1
  INTCON.INTE = 1
  PIE1        = %00000001                  'enable tmr1 overflow
  PIE2        = %00000001                  'enable ccp2 interrupt
  CCP2CON     = %00000101           'Interrupt on rising edge on RC1
  T1CON       = %00000001              'enable timer1 prescale 1:1
  Lcd_Init(PORTB)                          'D7 = port.7  D6 = port.6  D5 = 
port.5
  Lcd_Cmd(Lcd_Clear)                   'D4 = port.4  E  = port.3  RS = 
port.2
  trisb.0 = 1
  trisb.1 = 1
  Lcd_Out(1, 1, "tornio=")
  Lcd_Out(2, 1, "PC    =")
  Pwm_Init(10000)                      'RC2
  Pwm_Start
  TMR1L    = 0
  TMR1H    = 0
  dato     = Eeprom_Read(0)                    'memoria in caso di 
interferenze e reset
  olddato  = 1
  compensa = dato
  periodo  = 0
  periodo1 = 0
  period   = 0
  giri     = 0
  oldgiri  = 1
  giri2    = 1
  oldgiri2 = 1
  girim    = 128
  while true
    periodo = CCPR2L                                     'carica il registro 
basso
    periodo = periodo + (0x100 * CCPR2H)    'aggiungi registro alto
    periodo = periodo + (0x10000 * period)     'aggiungi conteggio degli 
overflow del timer1
    periodo = 120000000/periodo                     'numero calcolato 
da(fosc/4)*60 per ottenere direttamente i giri al minuto
    giri    = periodo
    if giri<>oldgiri then
       WordToStr(giri, txt)
       Lcd_Out(1, 8, txt)
       oldgiri=giri
    end if
    giri2=compensa*5
    if giri<giri2 then
      if girim>=255 then
         girim =255
      else
         inc(girim)
      end if
    else
      if girim<=0 then
         girim =0
      else
         dec(girim)
      end if
    end if
    if giri2<>oldgiri2 then
       WordToStr(giri2, txt)
       Lcd_Out(2, 8, txt)
       oldgiri2=giri2
    end if
     if dato<>olddato then
        Eeprom_Write(0, dato)               'memoria in caso di interferenze 
e reset
        olddato=dato
     end if
    Pwm_Change_Duty(girim)              'RC2 uscita PWM che comanda velocità 
motore
    Delay_ms(10)
  wend
end.

 Roberto
salve a tutti
ho risolto il problema della visualizzazione inserendo dei contatori che al 
massimo mi danno 10 aggiornamenti al secondo e modificando il conteggio dei 
giri nel seguente modo:
    periodo = period
    periodo = periodo<<8
    periodo = periodo + CCPR2H
    periodo = periodo<<8
    periodo = periodo + CCPR2L
    periodo = 120000000 div periodo
ho ottenuto la risoluzione di 1giro/min, troppo alta, quasi quasi la 
diminuisco :-)))
c'č qualcuno che mi spiega perchč cosě funziona e come l'avevo scritto prima 
no???
ciao
Roberto