faefa

Dependencies:   mbed CANMsg

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 
00002 //********************************************************************************************************************
00003 //********************************************************************************************************************
00004 // FIRMWARE SEMINATRICE MODULA
00005 // VERSIONE PER SCHEDA DI CONTROLLO CON DRIVER INTEGRATI
00006 // V4 - ATTENZIONE - LA VERSIONE V4 HA IL DRIVER STEPPER LV8727
00007 // IL MOTORE DC E' GESTITO CON IL DRIVER VNH3SP30-E E CON LA LETTURA
00008 // DELLA CORRENTE ASSORBITA TRAMITE IL CONVERTITORE MLX91210-CAS102 CON 50A FONDOSCALA
00009 // CHE FORNISCE UNA TENSIONE DI USCITA PARI A 40mV/A
00010 // FIRST RELEASE OF BOARD DEC 2017
00011 // FIRST RELEASE OF FIRMWARE JAN 2018
00012 //
00013 // THIS RELEASE: 09 JULY 2018
00014 //
00015 // APPLICATION: MODULA CON DISTRIBUTORE ZUCCA OPPURE RISO E PUO' FUNZIONARE ANCHE CON SENSORE A 25 FORI SUL DISCO O 
00016 //              ENCODER MOTORE SETTANDO GLI APPOSITI FLAGS
00017 //
00018 // 29 05 2018 - INSERITO SECONDO ENCODER VIRTUALE PER LA GESTIONE DEL SINCRONISMO TRA TAMBURO E RUOTA DI SEMINA
00019 //              IN PRATICA IL PRIMO ENCODER è SINCRONO CON IL SEGNALE DEI BECCHI E VIENE AZZERATO DA QUESTI, MENTRE
00020 //              IL SECONDO E' INCREMENTATO IN SINCRONO CON IL PRIMO MA AZZERATO DALLA FASE. IL SUO VALORE E' POI DIVISO
00021 //              PER IL RAPPORTO RUOTE E LA CORREZIONE AGISCE SULLA VELOCITA' DEL TAMBURO PER MANTENERE LA FASE DEL SECONDO
00022 //              ENCODER
00023 // 05 06 2018 - INSERITO IL CONTROLLO DI GESTIONE DEL QUINCONCE SENZA ENCODER
00024 // 09 06 2018 - INSERITO CONTROLLO DI FASE CON ENCODER MASTER PER QUINCONCE - DATO SCAMBIATO IN CAN
00025 //
00026 /********************
00027 IL FIRMWARE SI COMPONE DI 7 FILES:
00028     - main.cpp
00029     - main.hpp
00030     - iodefinition.hpp
00031     - canbus.hpp
00032     - parameters.hpp
00033     - timeandtick.hpp
00034     - variables.hpp
00035 ED UTILIZZA LE LIBRERIE STANDARD MBED PIU' UNA LIBRERIA MODIFICATA E DEDICATA PER IL CAN
00036 *********************
00037 LA MACCHINA UTILIZZA SEMPRE 2 SOLI SENSORI; UNO PER SENTIRE LE CELLE DI CARICO SEME ED UNO PER SENTIRE I BECCHI DI SEMINA.
00038 GLI AZIONAMENTI SONO COMPOSTI DA DUE MOTORI; UN DC PER IL CONTROLLO DELLA RUOTA DI SEMINA ED UNO STEPPER PER IL CONTROLLO DEL TAMBURO
00039 UN SENSORE AGGIUNTIVO SULL'ELEMENTO MASTER RILEVA LA VELOCITA' DI AVANZAMENTO
00040 UN SENSORE AGGIUNTIVO SULLA RUOTA DI SEMINA RILEVA LA ROTAZIONE DELLA RUOTA STESSA ATTRAVERSO FORI PRESENTI SUL DISCO DI SEMINA
00041 *********************
00042 LA LOGICA GENERALE PREVEDE CHE IL DC DELLA RUOTA DI SEMINA VENGA COMANDATO IN FUNZIONE DELLA VELOCITA' LETTA DAL SENSORE DI AVANZAMAENTO DEL MASTER
00043 IL PROBLEMA PRINCIPALE E' CHE QUANDO I BECCHI SONO INSERITI NEL TERRENO NON VI E' RETROAZIONE REALE SULLA VELOCITA' DI ROTAZIONE DELLA RUOTA STESSA 
00044 PROPRIO PERCHE' L'AVANZAMANETO NEL TERRENO IMPRIME UNA VELOCITA' PROPRIA AL BECCO E QUINDI ANCHE ALLA RUOTA.
00045 PER OVVIARE A QUESTO PROBLEMA SI E' INSERITO UN CONTROLLO DI CORRENTE ASSORBITA DAL DC; SE E' BASSA DEVO ACCELERARE, SE E' ALTA DEVO RALLENTARE
00046 IL VALORE DI RIFERIMENTO DELL'ANALOGICA DI INGRESSO VIENE AGGIORNATO OGNI VOLTA CHE LA RUOTA DI SEMINA E' FERMA
00047 IL TAMBURO SEGUE LA RUOTA DI SEMINA RILEVANDONE LA VELOCITA' E RICALCOLANDO LA PROPRIA IN FUNZIONE DELLA REALE VELOCITA' DI ROTAZIONE DELLA RUOTA DI SEMINA
00048 LA FASE VIENE DETERMINATA DAL PASSAGGIO DEI BECCHI SUL SENSORE RELATIVO.
00049 IL PROBLEMA PRINCIPALE NEL MANTENERE LA FASE DEL TAMBURO E' DATO DAL FATTO CHE LA SINCRONIZZAZIONE DELLA FASE SOLO SULL'IMPULSO DEL BECCO NON E' SUFFICIENTE
00050 SOPRATUTTO QUANDO I BECCHI SONO MOLTO DISTANZIATI.
00051 PER OVVIARE A QUESTO PROBLEMA SI SONO INSERITI DUE ENCODER VIRTUALI CHE SEZIONANO LA RUOTA DI SEMINA IN 9000 PARTI. ENTRAMBI VENGONO GESTITI DA UN GENERATORE DINAMICO DI CLOCK INTERNO
00052 TARATO SULLA REALE VELOCITA' DI ROTAZIONE DELLA RUOTA DI SEMINA.
00053 IL PRIMO ENCODER VIRTUALE SI OCCUPA DI DETERMINARE LA POSIZIONE FISICA DELLA RUOTA DI SEMINA E SI AZZERA AL PASSAGGIO DI OGNI BECCO.
00054 IL SECONDO VIENE AZZERATO DALL'IMPULSO DI FASE DEL PRIMO ENCODER DETERMINATO DAI VALORI IMPOSTI SUL TERMINALE TRITECNICA
00055 IL SECONDO ENCODER VIENE CONFRONTATO CON LA POSIZIONE ASSOLUTA DEL TAMBURO (DETERMINATA DAL NUMERO DI STEP EMESSI DAL CONTROLLO), RAPPORTATA TRA CELLE E BECCHI.
00056 IL CONFRONTO DETERMINA LA POSIZIONE RELATIVA DELLA SINGOLA CELLA RISPETTO AL SINGOLO BECCO. IL MANTENIMENTO DELLA SINCRONIZZAZIONE DI FASE, DETERMINA IL SINCRO CELLA/BECCO.
00057 LA SINCRONIZZAZIONE VIENE PERO' E' A SUA VOLTA RICALCOLATA SHIFTANDO LA POSIZIONE DI AZZERAMENTO DEL SECONDO ENCODER IN FUNZIONE DELLA VELOCITA' DI ROTAZIONE GENERALE AL FINE
00058 DI CAMBIARE L'ANGOLO DI ANTICIPO DI RILASCIO DEL SEME IN FUNZIONE DELLA VELOCITA' E RECUPERARE COSI' IL TEMPO DI VOLO DEL SEME.
00059 IL TAMBURO HA DUE TIPI DI FUNZIONAMENTO: CONTINUO E AD IMPULSI. E' SELEZIONABILE IN FUNZIONE DELLA VELOCITA' E DEL TIPO DI DISTRIBUTORE MONTATO.
00060 **********************
00061 TUTTI I VALORI, CELLE, BECCHI, IMPULSI VELOCITA', ANCGOLO DI AVVIO, FASE DI SEMINA, ECC.. SONO IMPOSTABILI DA PANNELLO OPERATORE
00062 I DATI SONO SCAMBIATI CON IL PANNELLO OPERATORE E CON GLI ALTRI MODULI ATTRAVERSO RETE CAN CON PROTOCOLLO FREESTYLE ATTRAVERSO INDIRIZZAMENTI DEDICATI
00063 AL MOMENTO NON E' POSSIBILE ATTRIBUIRE L'INIDIRIZZO BASE DELL'ELEMENTO DA TERMINALE OPERATORE MA SOLO IN FASE DI COMPILAZIONE DEL FIRMWARE.
00064 **********************
00065 ALTRE SEZIONI RIGUARDANO LA GENERAZIONE DEGLI ALLARMI, LA COMUNICAZIONE CAN, LA SIMULAZIONE DI LAVORO, LA GESTIONE DELLA DIAGNOSI ECC..
00066 IL MOTORE DC E' CONTROLLATO DA DIVERSE ROUTINE; LE PRIORITA' SONO (DALLA PIU' BASSA ALLA PIU' ALTA): CALCOLO TEORICO, RICALCOLO REALE, CONTROLLO DI FASE QUINCONCE, CONTROLLO DI CORRENTE.
00067 LO STEPPER SEGUE IL DC.
00068 **********************
00069 IN FASE DI ACCENSIONE ED OGNI QUALVOLTA SI ARRIVA A VELOCITA' ZERO, LA MACCHINA ESEGUE UN CICLO DI AZZERAMENTO
00070 NON ESISTE PULSANTE DI MARCIA/STOP; E' SEMPRE ATTIVA.
00071 **********************
00072 NEL PROGRAMMA E' PRESENTE UNA SEZIONE DI TEST FISICO DELLA SCHEDA ATTIVABILE SOLO IN FASE DI COMPILAZIONE
00073 **********************
00074 ALTRE FUNZIONI: PRECARICAMENTO DEL TAMBURO
00075                 AZZERAMENTO MANUALE
00076                 STATISTICA DI SEMINA    (CONTA LE CELLE)
00077 */
00078 //********************************************************************************************************************
00079 //********************************************************************************************************************
00080 
00081 #include "main.hpp"
00082 #include "timeandtick.hpp"
00083 #include "canbus.hpp"
00084 #include "watchdog.h"
00085 #include "iodefinition.hpp"
00086 #include "parameters.hpp"
00087 #include "variables.hpp"
00088 //********************************************************************************************************************
00089 //********************************************************************************************************************
00090 // ------------------------------------------------------------------------------------------------------------------------------------------------------------------
00091 // TASK SECTION
00092 // ------------------------------------------------------------------------------------------------------------------------------------------------------------------
00093 //************************************************************************
00094 //************************************************************************
00095 // rise of seed speed 25 pulse sensor
00096 void sd25Fall(){
00097     timeHole=metalTimer.read_ms();
00098     int memo_TimeHole= (memoTimeHole + timeHole)/ (int)2;
00099     memoTimeHole = timeHole;
00100     metalTimer.reset();
00101     if (speedFromPick==0){
00102         speedOfSeedWheel=((seedPerimeter/25.0f)/(double)memo_TimeHole)*1000.0f;    //mtS
00103     }
00104 }
00105 // rise of seed speed motor encoder
00106 void encoRise(){
00107     timeHole=metalTimer.read_us();
00108     int memo_TimeHole= (memoTimeHole + timeHole)/ (int)2;
00109     memoTimeHole = timeHole;
00110     metalTimer.reset();
00111     if (encoder==true){
00112         speedOfSeedWheel=((seedPerimeter/((SDreductionRatio*25.5f)))/(double)memo_TimeHole)*1000000.0f;    //mtS
00113         pulseRised2=1;
00114     }
00115 }
00116 // rise of seed presence sensor
00117 void seedSensorTask(){
00118     seedSee=1;
00119 }
00120 //**************************************************
00121 // generate speed clock when speed is simulated from Tritecnica display
00122 void speedSimulationClock(){        
00123     lastPulseRead=speedTimer.read_us();
00124     oldLastPulseRead=lastPulseRead;
00125     speedTimer.reset();
00126     pulseRised=1;
00127     speedFilter.reset();
00128 }
00129 //*******************************************************
00130 //    interrupt task for tractor speed reading
00131 //*******************************************************
00132 void tractorReadSpeed(){
00133     if ((oldTractorSpeedRead==0)){
00134         lastPulseRead=speedTimer.read_us();
00135         oldLastPulseRead=lastPulseRead;
00136         speedTimer.reset();
00137         pulseRised=1;
00138         oldTractorSpeedRead=1;
00139         spazioCoperto+= pulseDistance;
00140     }
00141     speedFilter.reset();
00142     speedClock=1;
00143 }
00144 //*******************************************************
00145 void speedMediaCalc(){
00146     double lastPd=(double) lastPulseRead/1000.0f;
00147     pulseSpeedInterval = (mediaSpeed[0]+lastPd)/2.0f;
00148     if (enableSimula==1){
00149         double TMT = (double)(speedSimula) * 100.0f /3600.0f;
00150         pulseSpeedInterval = pulseDistance / TMT;
00151     }    
00152     mediaSpeed[0]=lastPd;
00153     OLDpulseSpeedInterval=pulseSpeedInterval;
00154 }    
00155 
00156 //*******************************************************
00157 //    clocked task for manage virtual encoder of seed wheel i/o
00158 //*******************************************************
00159 //*******************************************************
00160 void step_SDPulseOut(){
00161     SDactualPosition++;
00162     prePosSD++;
00163     #if defined(speedMaster)
00164         posForQuinc++;
00165     #endif
00166 }
00167 //*******************************************************
00168 void step_TBPulseOut(){
00169     TBmotorStepOut=!TBmotorStepOut;
00170     if (TBmotorStepOut==0){
00171         TBactualPosition++;
00172     }
00173 }
00174 //*******************************************************
00175 // aggiornamento parametri di lavoro fissi e da Tritecnica
00176 void aggiornaParametri(){
00177     speedPerimeter = Pi * speedWheelDiameter ;                          // perimeter of speed wheel
00178     pulseDistance = (speedPerimeter / speedWheelPulse)*1000.0f;         // linear space between speed wheel pulse
00179     seedPerimeter = Pi * (seedWheelDiameter-(deepOfSeed*2.0f));         // perimeter of seed wheel
00180     intraPickDistance = seedPerimeter/pickNumber;
00181     K_WheelRPM = 60.0f/seedPerimeter;                                   // calcola il K per i giri al minuto della ruota di semina
00182     K_WhellFrequency = (seedWheelMotorSteps*SDreductionRatio)/60.0f;    // calcola il K per la frequenza di comando del motore di semina
00183     rapportoRuote = pickNumber/cellsNumber;                             // calcola il rapporto tra il numero di becchi ed il numero di celle
00184     K_percentuale = TBmotorSteps*TBreductionRatio;
00185     SDsectorStep = (double)fixedStepGiroSD / (double)pickNumber;
00186     TBsectorStep = (TBmotorSteps*TBreductionRatio)/cellsNumber;
00187     KcorT = (SDsectorStep/TBsectorStep);///2.0f;
00188     angoloFase=angoloPh;
00189     avvioGradi=angoloAv;
00190     stepGrado=fixedStepGiroSD/360.0f;
00191     TBdeltaStep=(fixedStepGiroSD/pickNumber)+(stepGrado*avvioGradi);
00192     TBfaseStep = (stepGrado*angoloFase); 
00193     K_WheelRPM = 60.0f/seedPerimeter;                                   // calcola il K per i giri al minuto della ruota di semina  25.4                25,40
00194     TBgiroStep = TBmotorSteps*TBreductionRatio;
00195     K_TBfrequency = TBgiroStep/60.0f;                                   // 1600 * 1.65625f /60 = 44                                                     44,00
00196     if (speedFromPick==1) {
00197         intraPickDistance = seedPerimeter/pickNumber;
00198     }else{
00199         intraPickDistance = seedPerimeter/25.0f;        // 25 è il numero di fori presenti nel disco di semina
00200     }
00201 }
00202 //*******************************************************
00203 void cambiaTB(double perio){
00204     // update TB frequency
00205     double TBper=0.0f;
00206     if (aspettaStart==0){
00207         if (perio<250.0f){perio=500.0f;}
00208         double scala =0.0f;
00209         if (lowSpeed==1){
00210             scala =2.0f;
00211         }else{
00212             scala =1.8f;
00213         }
00214         TBper=perio/scala;
00215         if (oldPeriodoTB!=TBper){
00216             if (TBper >= 250.0f){
00217                 TBticker.attach_us(&step_TBPulseOut,TBper);  // clock time are milliseconds and attach seed motor stepper controls
00218             }else{
00219                 TBticker.detach();
00220             }
00221             oldPeriodoTB=TBper;
00222         }
00223     }
00224 }
00225 //*******************************************************
00226 void seedCorrect(){
00227     /*
00228     posError determina la posizione relativa di TB rispetto ad SD
00229     la reale posizione di SD viene modificata in funzione della velocità per 
00230     traslare la posizione relativa di TB. All'aumentare della velocità la posizione
00231     di SD viene incrementata così che TB acceleri per raggiungerla in modo da rilasciare il seme prima
00232     La taratura del sistema avviene determinando prima il valore di angoloFase alla minima velocità,
00233     poi, alla massima velocità, dovrebbe spostarsi la posizione relativa con una variabile proporzionale alla velocità, ma c'è un però.
00234     Il problema è che il momento di avvio determina una correzione dell'angolo di partenza del tamburo
00235     angolo che viene rideterminato ogni volta che il sensore becchi legge un transito.
00236     Di fatto c'è una concorrenza tra l'angolo di avvio determinato e la correzione di posizione relativa
00237     del tamburo. E' molto probabile che convenga modificare solo la posizione relativa e non anche l'angolo di avvio
00238     Ancora di più se viene eliminata la parte gestita da ciclata.
00239     In questo modo dovrebbe esserci solo un andamento in accelerazione di TB che viene poi eventualmente decelerato
00240     dal passaggio sul sensore di TB. Funzione corretta perchè il sincronismo tra i sensori genera l'inibizione della correzione
00241     di fase di TB. In pratica il ciclo viene resettato al passaggio sul sensore di SD che riporta a 0 la posizione di SD.
00242     Appena il sensore di TB viene impegnato allora viene abilitato il controllo di fase del tamburo.
00243     Questo si traduce nel fatto che il controllo di posizione viene gestito solo all'interno di uno slot di semina in modo che
00244     il tamburo non risenta della condizione di reset della posizione di SD mentre lui è ancora nella fase precedente. Si fermerebbe.
00245     
00246     // La considerazione finale è che mantenendo l'angolo di avvio fisso e regolato sulla bassa velocità, intervenendo solo sulla correzione
00247     // di posizione in questa routine, dovrebbe essere possibile seminare correttamente a tutte le velocità regolando solo 2 parametri.
00248     */            
00249     /*
00250     SDsectorStep = (double)fixedStepGiroSD / (double)pickNumber;
00251     TBsectorStep = (TBmotorSteps*TBreductionRatio)/cellsNumber;
00252     KcorT = (SDsectorStep/TBsectorStep);
00253     angoloFase=angoloPh;
00254     stepGrado=fixedStepGiroSD/360.0f;
00255     avvioGradi = costante da terminale tritecnica
00256     TBdeltaStep=(fixedStepGiroSD/pickNumber)-(stepGrado*avvioGradi);
00257     TBfaseStep = (stepGrado*angoloFase); 
00258     */
00259 
00260     if ((tractorSpeed_MtS_timed>0.01f)){
00261         if (inhibit==0){
00262             double posError =0.0f;
00263             double posSD=((double)SDactualPosition)/KcorT;
00264             posError = posSD - (double)TBactualPosition;    
00265             // interviene sulla velocità di TB per raggiungere la corretta posizione relativa
00266             if((lowSpeed==0)&&(aspettaStart==0)){
00267                 if (posError>50.0f){posError=50.0f;}
00268                 if (posError<-50.0f){posError=-50.0f;}
00269                 if ((posError >=1.0f)||(posError<=-1.0f)){   
00270                     ePpos = periodo /(1.0f+ ((posError/100.0f)));
00271                     cambiaTB(ePpos);
00272                 }
00273             }
00274         }
00275     }
00276 }
00277 //*******************************************************
00278 void videoUpdate(){
00279     for(int aa=0;aa<4;aa++){speedForDisplay[aa]=speedForDisplay[aa+1];}
00280     speedForDisplay[4]=tractorSpeed_MtS_timed;
00281     totalSpeed=0.0f;
00282     for (int aa=0; aa<5; aa++){totalSpeed += speedForDisplay[aa];}
00283     totalSpeed = totalSpeed / 5.0f;
00284         #if defined(pcSerial)
00285             #if defined(SDreset)
00286                 pc.printf("Fase: %d",fase);
00287                 pc.printf(" PrePosSD: %d",prePosSD);
00288                 pc.printf(" PosSD: %d",SDactualPosition);
00289                 pc.printf(" speed: %f",tractorSpeed_MtS_timed);
00290                 pc.printf(" Trigger: %d \n", trigRepos);
00291             #endif
00292         #endif
00293 }
00294 //*******************************************************
00295 void ciclaTB(){
00296     if ((startCicloTB==1)&&(cicloTbinCorso==0)){
00297         TBticker.attach_us(&step_TBPulseOut,TBperiod/2.5f);  // clock time are milliseconds and attach seed motor stepper controls
00298         cicloTbinCorso = 1;
00299         startCicloTB=0;
00300     }
00301     if ((loadDaCan==1)&&(loadDaCanInCorso==0)){
00302         TBticker.attach_us(&step_TBPulseOut,1000.0f);  // clock time are milliseconds and attach seed motor stepper controls
00303         loadDaCanInCorso=1;
00304         stopCicloTB=0;
00305     }
00306     if ((stopCicloTB==1)&&(TBactualPosition>5)){
00307         TBticker.detach();
00308         cicloTbinCorso = 0;
00309         stopCicloTB=0;
00310         loadDaCanInCorso=0;
00311         loadDaCan=0;
00312     }
00313 }
00314 // ------------------------------------------------------------------------------------------------------------------------------------------------------------------
00315 void stepSetting(){
00316     // Stepper driver init and set
00317     TBmotorRst=1;                               // reset stepper driver
00318     TBmotorDirecti=1;                           // reset stepper direction
00319     // M1   M2  M3  RESOLUTION
00320     // 0    0   0       1/2
00321     // 1    0   0       1/8
00322     // 0    1   0       1/16
00323     // 1    1   0       1/32
00324     // 0    0   1       1/64
00325     // 1    0   1       1/128
00326     // 0    1   1       1/10
00327     // 1    1   1       1/20
00328     if (TBmotorSteps==400){
00329         TBmotor_M1=1;
00330         TBmotor_M2=1;
00331         TBmotor_M3=1;
00332     }else if (TBmotorSteps==1600){
00333         TBmotor_M1=0;
00334         TBmotor_M2=1;
00335         TBmotor_M3=1;
00336     }else if (TBmotorSteps==3200){
00337         TBmotor_M1=1;
00338         TBmotor_M2=0;
00339         TBmotor_M3=1;
00340     }else if (TBmotorSteps==6400){
00341         TBmotor_M1=0;
00342         TBmotor_M2=0;
00343         TBmotor_M3=1;
00344     }else if (TBmotorSteps==12800){
00345         TBmotor_M1=1;
00346         TBmotor_M2=1;
00347         TBmotor_M3=0;
00348     }else if (TBmotorSteps==25600){
00349         TBmotor_M1=0;
00350         TBmotor_M2=1;
00351         TBmotor_M3=0;
00352     }else if (TBmotorSteps==2000){
00353         TBmotor_M1=1;
00354         TBmotor_M2=0;
00355         TBmotor_M3=0;
00356     }else if (TBmotorSteps==4000){
00357         TBmotor_M1=0;
00358         TBmotor_M2=0;
00359         TBmotor_M3=0;
00360     }
00361     TBmotorRst=0;
00362 }
00363 //****************************************
00364 void dcSetting(){
00365         if ((speedFromPick==0)&&(encoder==false)){
00366             DcEncoder.rise(&sd25Fall);
00367         }
00368         if (encoder==true){
00369             DcEncoder.rise(&encoRise);
00370             //ElementPosition.fall(&encoRise);
00371         }
00372 }
00373 //*******************************************************
00374 void allarmi(){
00375         uint8_t alarmLowRegister1=0x00;
00376         alarmLowRegister=0x00;
00377         alarmHighRegister=0x80;
00378 
00379         //alarmLowRegister=alarmLowRegister+(all_semiFiniti*0x01);    // manca il sensore
00380         alarmLowRegister=alarmLowRegister+(all_pickSignal*0x02);    // fatto
00381         alarmLowRegister=alarmLowRegister+(all_cellSignal*0x04);    // fatto
00382         alarmLowRegister=alarmLowRegister+(all_lowBattery*0x08);    // fatto
00383         alarmLowRegister=alarmLowRegister+(all_overCurrDC*0x10);    // fatto
00384         alarmLowRegister=alarmLowRegister+(all_stopSistem*0x20);    // verificarne la necessità
00385         //alarmLowRegister=alarmLowRegister+(all_upElements*0x40);    // manca il sensore
00386         if (seedSensorEnable==true){
00387             alarmLowRegister=alarmLowRegister+(all_noSeedOnCe*0x80);    // manca il sensore
00388         }
00389 
00390         //alarmLowRegister1=alarmLowRegister1+(all_cfgnErrors*0x01);    // da scrivere
00391         alarmLowRegister1=alarmLowRegister1+(all_noDcRotati*0x02);    // fatto
00392         alarmLowRegister1=alarmLowRegister1+(all_noStepRota*0x04);    // fatto
00393         alarmLowRegister1=alarmLowRegister1+(all_speedError*0x08);    // fatto
00394         alarmLowRegister1=alarmLowRegister1+(all_noSpeedSen*0x10);    // fatto
00395         alarmLowRegister1=alarmLowRegister1+(all_no_Zeroing*0x20);    // fatto
00396         alarmLowRegister1=alarmLowRegister1+(all_genericals*0x40);
00397         if (alarmLowRegister1 > 0){
00398             alarmHighRegister = 0x81;
00399             alarmLowRegister = alarmLowRegister1;
00400         }
00401 
00402         #if defined(pcSerial)
00403             #if defined(VediAllarmi)
00404                 if (all_pickSignal==1){pc.printf("AllarmeBecchi\n");}
00405                 if (all_cellSignal==1){pc.printf("AllarmeCelle\n");}
00406                 if (all_lowBattery==1){pc.printf("AllarmeBassaCorrente\n");}
00407                 if (all_overCurrDC==1){pc.printf("AllarmeAltaCorrente\n");}
00408                 if (all_stopSistem==1){pc.printf("AllarmeStop\n");}
00409                 if (all_noDcRotati==1){pc.printf("AllarmeDCnoRotation\n");}
00410                 if (all_noStepRota==1){pc.printf("AllarmeNoStepRotation\n");}
00411                 if (all_speedError==1){pc.printf("AllarmeSpeedError\n");}
00412                 if (all_noSpeedSen==1){pc.printf("AllarmeNoSpeedSensor\n");}
00413                 if (all_no_Zeroing==1){pc.printf("AllarmeNoZero\n");}
00414                 if (all_genericals==1){pc.printf("AllarmeGenerico\n");}
00415                 pc.printf("Code: 0x%x%x\n",alarmHighRegister,alarmLowRegister);
00416             #endif
00417         #endif
00418         all_semiFiniti=0;
00419         all_pickSignal=0;
00420         all_cellSignal=0;
00421         all_lowBattery=0;
00422         all_overCurrDC=0;
00423         all_stopSistem=0;
00424         all_upElements=0;
00425         all_noSeedOnCe=0;
00426         all_cfgnErrors=0;
00427         all_noDcRotati=0;
00428         all_noStepRota=0;
00429         all_speedError=0;
00430         all_noSpeedSen=0;
00431         all_no_Zeroing=0;
00432         all_genericals=0;
00433 }
00434 //*******************************************************
00435 #if defined(speedMaster)
00436     void upDateSincro(){
00437         char val1[8]={0,0,0,0,0,0,0,0};
00438         val1[3]=(posForQuinc /0x00FF0000)&0x000000FF;
00439         val1[2]=(posForQuinc /0x0000FF00)&0x000000FF;
00440         val1[1]=(posForQuinc /0x000000FF)&0x000000FF;
00441         val1[0]=posForQuinc & 0x000000FF;
00442         //double pass = tractorSpeed_MtS_timed*100.0f;
00443         double pass = speedOfSeedWheel*100.0f;
00444         val1[4]=(uint8_t)(pass)&0x000000FF;
00445         val1[5]=(prePosSD /0x0000FF00)&0x000000FF;
00446         val1[6]=(prePosSD /0x000000FF)&0x000000FF;
00447         val1[7]=prePosSD & 0x000000FF;
00448         #if defined(canbusActive)
00449             #if defined(speedMaster)
00450                 if(can1.write(CANMessage(TX_SI, *&val1,8))){
00451                     checkState=0;
00452                 }
00453             #endif
00454         #endif
00455     }
00456 #endif
00457 //*******************************************************
00458 void upDateSpeed(){
00459     /*
00460     aggiorna dati OPUSA3
00461     val1[0] contiene il dato di velocità
00462     val1[1] contiene il byte basso della tabella allarmi
00463         uint8_t all_semiFiniti = 0;     // semi finiti (generato dal relativo sensore)
00464         uint8_t all_pickSignal = 0;     // errore segnale becchi (generato dal tempo tra un becco ed il successivo)
00465         uint8_t all_cellSignal = 0;     // errore segnale celle (generato dal sensore tamburo )
00466         uint8_t all_lowBattery = 0;     // allarme batteria (valore interno di tritecnica)
00467         uint8_t all_overCurrDC = 0;     // sovracorrente motore DC  (generato dal sensore di corrente)
00468         uint8_t all_stopSistem = 0;     // sistema in stop (a tempo con ruota ferma)
00469         uint8_t all_upElements = 0;     // elementi sollevati   (generato dal relativo sensore)
00470         uint8_t all_noSeedOnCe = 0;     // fallanza di semina (manca il seme nella cella)
00471         uint8_t all_cfgnErrors = 0;     // errore di configurazione     (incongruenza dei parametri impostati)
00472         uint8_t all_noDcRotati = 0;     // ruota di semina bloccata (arriva la velocità ma non i becchi)
00473         uint8_t all_noStepRota = 0;     // tamburo di semina bloccato   (comando il tamburo ma non ricevo il sensore)
00474         uint8_t all_speedError = 0;     // errore sensore velocità  (tempo impulsi non costante)
00475         uint8_t all_noSpeedSen = 0;     // mancanza segnale di velocità (sento i becchi ma non la velocita)
00476         uint8_t all_no_Zeroing = 0;     // mancato azzeramento sistema (generato dal timeout del comando motore DC)
00477         uint8_t all_genericals = 0;     // allarme generico
00478     val1[2] contiene il byte alto della tabella di allarmi
00479     val1[3] contiene i segnali per la diagnostica
00480         bit 0= sensore ruota fonica
00481         bit 1= sensore celle
00482         bit 2= sensore posizione
00483         bit 3= sensore becchi
00484         bit 4= motore DC
00485         bit 5= controller
00486         bit 6= motore stepper
00487     */
00488         char val1[8]={0,0,0,0,0,0,0,0};
00489 
00490         val1[3]=0;
00491         val1[3]=val1[3]+(tractorSpeedRead*0x01);
00492         val1[3]=val1[3]+(TBzeroPinInput*0x02);
00493         val1[3]=val1[3]+(DcEncoder*0x04);
00494         val1[3]=val1[3]+(seedWheelZeroPinInput*0x08);
00495     #if defined(simulaPerCan)
00496         if (buttonUser==0){
00497             val1[1]=0x02;
00498         }else{
00499             val1[1]=0x00;
00500         }
00501         val1[3]=valore;
00502         valore+=1;
00503         if(valore>50){
00504             valore=0;
00505         }
00506         tractorSpeed_MtS_timed=valore;
00507     #endif
00508     allarmi();
00509     valore = totalSpeed*36.0f; // tractorSpeed_MtS_timed*36.0f;
00510     val1[0]=valore;
00511     val1[1]=alarmHighRegister;   // registro alto allarmi. Parte sempre da 0x80
00512     val1[2]=alarmLowRegister;   // registro basso allarmi
00513     //val1[3]=val1[3];// registro di stato degli ingressi
00514     val1[4]=resetComandi;
00515     val1[5]=cellsCounterLow;
00516     val1[6]=cellsCounterHig;
00517     #if defined(canbusActive)
00518         if(can1.write(CANMessage(TX_ID, *&val1,8))){
00519             checkState=0;
00520         }
00521     #endif
00522 }
00523 //*******************************************************
00524 void leggiCAN(){
00525     #if defined(canbusActive)
00526         if(can1.read(rxMsg)) {
00527             if (firstStart==1){
00528                 #if defined(speedMaster)
00529                     sincUpdate.attach(&upDateSincro,0.009f);
00530                     canUpdate.attach(&upDateSpeed,0.21f);
00531                 #else
00532                     canUpdate.attach(&upDateSpeed,0.407f);
00533                 #endif
00534                 firstStart=0;
00535             }
00536             
00537             if (rxMsg.id==RX_ID){
00538                 #if defined(pcSerial)
00539                     #if defined(canDataReceiveda)
00540                         pc.printf("Messaggio ricevuto\n");
00541                     #endif
00542                 #endif
00543             }
00544             if (rxMsg.id==RX_Broadcast){
00545                 #if defined(pcSerial)
00546                     #if defined(canDataReceivedb)
00547                         pc.printf("BroadCast ricevuto\n");
00548                     #endif
00549                 #endif
00550                 enableSimula= rxMsg.data[0];
00551                 speedSimula = rxMsg.data[1];
00552                 avviaSimula = rxMsg.data[2];
00553                 selezionato = rxMsg.data[3];
00554                 comandiDaCan = rxMsg.data[4];
00555                 #if defined(pcSerial)
00556                     #if defined(canDataReceived)
00557                         pc.printf("Speed simula %d \n",speedSimula);
00558                     #endif
00559                 #endif
00560                 switch (comandiDaCan){
00561                     case 1:
00562                     case 3:
00563                         azzeraDaCan=1;
00564                         resetComandi=0x01;
00565                         comandiDaCan=0;
00566                         break;
00567                     case 2:
00568                         loadDaCan=1;
00569                         resetComandi=0x02;
00570                         comandiDaCan=0;
00571                         break;
00572                     default:
00573                         comandiDaCan=0;
00574                         resetComandi=0xFF;
00575                         break;
00576                 }
00577                 #if defined(pcSerial)
00578                     #if defined(canDataReceivedR)
00579                         pc.printf("Comandi: %x\n",resetComandi);
00580                     #endif
00581                 #endif
00582                 if (speedSimula>45){
00583                     speedSimula=45;
00584                 }
00585                 // modulo 1
00586                 if (RX_ID==0x100){
00587                     if ((selezionato&0x01)==0x01){
00588                         simOk=1;
00589                     }else{
00590                         simOk=0;
00591                     }
00592                 }
00593                 // modulo 2
00594                 if (RX_ID==0x102){
00595                     if ((selezionato&0x02)==0x02){
00596                         simOk=1;
00597                     }else{
00598                         simOk=0;
00599                     }
00600                 }
00601                 // modulo 3
00602                 if (RX_ID==0x104){
00603                     if ((selezionato&0x04)==0x04){
00604                         simOk=1;
00605                     }else{
00606                         simOk=0;
00607                     }
00608                 }
00609                 // modulo 4
00610                 if (RX_ID==0x106){
00611                     if ((selezionato&0x08)==0x08){
00612                         simOk=1;
00613                     }else{
00614                         simOk=0;
00615                     }
00616                 }
00617                 // modulo 5
00618                 if (RX_ID==0x108){
00619                     if ((selezionato&0x10)==0x10){
00620                         simOk=1;
00621                     }else{
00622                         simOk=0;
00623                     }
00624                 }
00625                 
00626             }
00627             if (rxMsg.id==RX_Settings){
00628                 if (tractorSpeed_MtS_timed==0.0f){
00629                     pickNumber = rxMsg.data[0];               // numero di becchi installati sulla ruota di semina
00630                     cellsNumber = rxMsg.data[1];             // numero di celle del tamburo
00631                     deepOfSeed=(rxMsg.data[2]/10000.0f);                // deep of seeding 
00632                     seedWheelDiameter = ((rxMsg.data[4]*0xFF)+rxMsg.data[3])/10000.0f;      // seed wheel diameter setting
00633                     speedWheelDiameter = ((rxMsg.data[6]*0xFF)+rxMsg.data[5])/10000.0f;     // variable for tractor speed calculation (need to be set from UI) ( Unit= meters )
00634                     speedWheelPulse = rxMsg.data[7];          // variable which define the number of pulse each turn of tractor speed wheel (need to be set from UI)
00635                     aggiornaParametri();
00636                 }
00637             }
00638             if (rxMsg.id==RX_AngoloPh){
00639                 if (tractorSpeed_MtS_timed==0.0f){
00640                     #if defined(M1)
00641                         angoloPh = (double) rxMsg.data[0] ;
00642                         aggiornaParametri();
00643                     #endif
00644                     #if defined(M2)
00645                         angoloPh = (double) rxMsg.data[1] ;
00646                         aggiornaParametri();
00647                     #endif
00648                     #if defined(M3)
00649                         angoloPh = (double) rxMsg.data[2] ;
00650                         aggiornaParametri();
00651                     #endif
00652                     #if defined(M4)
00653                         angoloPh = (double) rxMsg.data[3] ;
00654                         aggiornaParametri();
00655                     #endif
00656                     #if defined(M5)
00657                         angoloPh = (double) rxMsg.data[4] ;
00658                         aggiornaParametri();
00659                     #endif
00660                     #if defined(M6)
00661                         angoloPh = (double) rxMsg.data[5] ;
00662                         aggiornaParametri();
00663                     #endif
00664                 }
00665             }
00666             if (rxMsg.id==RX_AngoloAv){
00667                 if (tractorSpeed_MtS_timed==0.0f){
00668                     #if defined(M1)
00669                         angoloAv = (double) rxMsg.data[0] ;
00670                         aggiornaParametri();
00671                     #endif
00672                     #if defined(M2)
00673                         angoloAv = (double) rxMsg.data[1] ;
00674                         aggiornaParametri();
00675                     #endif
00676                     #if defined(M3)
00677                         angoloAv = (double) rxMsg.data[2] ;
00678                         aggiornaParametri();
00679                     #endif
00680                     #if defined(M4)
00681                         angoloAv = (double) rxMsg.data[3] ;
00682                         aggiornaParametri();
00683                     #endif
00684                     #if defined(M5)
00685                         angoloAv = (double) rxMsg.data[4] ;
00686                         aggiornaParametri();
00687                     #endif
00688                     #if defined(M6)
00689                         angoloAv = (double) rxMsg.data[5] ;
00690                         aggiornaParametri();
00691                     #endif
00692                 }
00693             }
00694             if (rxMsg.id==RX_Quinconce){
00695                 if (tractorSpeed_MtS_timed==0.0f){
00696                     quinconceActive = (uint8_t) rxMsg.data[0];    
00697                     quincPIDminus = (uint8_t) rxMsg.data[1];          
00698                     quincPIDplus = (uint8_t) rxMsg.data[2];          
00699                     quincLIMminus = (uint8_t) rxMsg.data[3];          
00700                     quincLIMplus = (uint8_t) rxMsg.data[4];      
00701                     quincSector = (uint8_t) rxMsg.data[5];
00702                     aggiornaParametri();
00703                 }
00704             }
00705             if (rxMsg.id==RX_QuincSinc){
00706                 masterSinc = (uint32_t) rxMsg.data[3] * 0x00FF0000;              
00707                 masterSinc = masterSinc + ((uint32_t) rxMsg.data[2] * 0x0000FF00);              
00708                 masterSinc = masterSinc + ((uint32_t) rxMsg.data[1] * 0x000000FF);              
00709                 masterSinc = masterSinc + ((uint32_t) rxMsg.data[0]);
00710                 speedFromMaster = (double)rxMsg.data[4]/100.0f;
00711                 mast2_Sinc = ((uint32_t) rxMsg.data[5] * 0x0000FF00);              
00712                 mast2_Sinc = mast2_Sinc + ((uint32_t) rxMsg.data[6] * 0x000000FF);              
00713                 mast2_Sinc = mast2_Sinc + ((uint32_t) rxMsg.data[7]);
00714                 canDataCheck=1;
00715             }
00716             if (rxMsg.id==RX_Configure){
00717                 uint8_t flags = rxMsg.data[0];
00718                 uint16_t steps = (uint32_t) rxMsg.data[1]*0xFF00;
00719                 steps = steps + ((uint32_t)rxMsg.data[2]);
00720                 stepSetting();
00721                 cellsCountSet = rxMsg.data[3];
00722                 if ((flags&0x01)==0x01){
00723                     if (encoder==false){
00724                         encoder=true;
00725                         DcEncoder.rise(NULL);
00726                         dcSetting();
00727                     }
00728                 }else{
00729                     if (encoder==true){
00730                         encoder=false;
00731                         DcEncoder.rise(NULL);
00732                         dcSetting();
00733                     }
00734                 }
00735                 if ((flags&0x02)==0x02){
00736                     tankLevelEnable=true;
00737                 }else{
00738                     tankLevelEnable=false;
00739                 }
00740                 if ((flags&0x04)==0x04){
00741                     seedSensorEnable=true;
00742                 }else{
00743                     seedSensorEnable=false;
00744                 }
00745                 if ((flags&0x08)==0x08){
00746                     stendiNylonEnable=true;
00747                 }else{
00748                     stendiNylonEnable=false;
00749                 }
00750                 if ((flags&0x10)==0x10){
00751                     canDataCheckEnable=true;
00752                 }else{
00753                     canDataCheckEnable=false;
00754                 }
00755                 if ((flags&0x20)==0x20){
00756                     tamburoStandard=1;
00757                 }else{
00758                     tamburoStandard=0;
00759                 }
00760                 if ((flags&0x40)==0x40){
00761                     currentCheckEnable=true;
00762                 }else{
00763                     currentCheckEnable=false;
00764                 }
00765             }
00766         } 
00767     #endif
00768     #if defined(overWriteCanSimulation)
00769         enableSimula=1;
00770         speedSimula=25;
00771         avviaSimula=1;
00772         simOk=1;
00773     #endif
00774     
00775 }
00776 
00777 //*******************************************************
00778 void DC_CheckCurrent(){
00779     
00780     // TODO: tabella di riferimento assorbimenti alle varie velocità al fine di gestire
00781     //       gli allarmi e le correzioni di velocità
00782     
00783     //float SD_analogMatrix[10]={0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f};
00784     //int SD_analogIndex[10]={0,0,0,0,0,0,0,0,0,0};
00785     // Analog reading
00786     //number = floor(number * 100) / 100;
00787     //if (pwmCheck==1){
00788         timeout.detach();
00789         for (int ii=1;ii<20;ii++){
00790             SD_analogMatrix[ii]=SD_analogMatrix[ii+1];
00791         }
00792         SD_CurrentAnalog = floor(SDcurrent.read()*100)/100;              // valore in ingresso compreso tra 0.00 e 1.00
00793         SD_analogMatrix[20]=SD_CurrentAnalog;
00794         if (SDmotorPWM==0.0f){
00795             SD_CurrentStart=SD_CurrentAnalog;
00796         }
00797         float sommaTutto=0.0f;
00798         for (int ii=1;ii<21;ii++){
00799             sommaTutto=sommaTutto+SD_analogMatrix[ii];
00800         }
00801         float SD_CurrentAnalogica=sommaTutto/20.0f;
00802         SD_CurrentScaled = floor((  (SD_CurrentAnalogica - SD_CurrentStart)*3.3f)  /  (SD_CurrentFactor/1000.0f)*10)/10;
00803         #if defined(pcSerial)
00804             #if defined(correnteAssorbita)
00805                 pc.printf("CorrenteStart: %f ",SD_CurrentStart);
00806                 pc.printf(" CorrenteScaled: %f ",SD_CurrentScaled);
00807                 pc.printf(" CorrenteMedia: %f \n",SD_CurrentAnalogica);
00808             #endif
00809         #endif   
00810         reduceCurrent=false;
00811         incrementCurrent=false;
00812         /*
00813         if (SD_CurrentScaled < 3.0f){
00814             #if defined(canbusActive)
00815                 all_lowBattery=1;
00816             #endif
00817             incrementCurrent=true;
00818         }
00819         */
00820         if (SD_CurrentScaled > 10.0f){
00821             timeCurr.start();
00822             if (timeCurr.read() > 5.0f){
00823                 #if defined(canbusActive)
00824                     all_overCurrDC=1;
00825                 #endif
00826                 reduceCurrent=true;
00827                 timeCurr.reset();
00828             }
00829         }else{
00830             timeCurr.stop();
00831         }
00832     //}
00833 }
00834 //*******************************************************
00835 void DC_prepare(){
00836     // direction or brake preparation
00837     if (DC_brake==1){
00838         SDmotorInA=1;
00839         SDmotorInB=1;
00840     }else{
00841         if (DC_forward==1){
00842             SDmotorInA=1;
00843             SDmotorInB=0;
00844         }else{
00845             SDmotorInA=0;
00846             SDmotorInB=1;
00847         }
00848     }
00849     // fault reading
00850     if (SDmotorInA==1){SD_faultA=1;}else{SD_faultA=0;}
00851     if (SDmotorInB==1){SD_faultB=1;}else{SD_faultB=0;}
00852 }
00853 //*******************************************************
00854 void startDelay(){
00855     int ritardo =0;
00856     ritardo = (int)((float)(dcActualDuty*800.0f));
00857     timeout.attach_us(&DC_CheckCurrent,ritardo);
00858 }
00859 //*******************************************************
00860 void quincTrigon(){
00861     quincClock=true;
00862 }
00863 void quincTrigof(){
00864     quincClock=false;
00865 }
00866 //*******************************************************
00867 void quinCalc(){
00868     // riceve l'impulso di sincro dal master e fa partire il timer di verifica dell'errore
00869     #if !defined(mezzo)
00870         if ((quincClock==true)&&(oldQuincIn==0)){
00871             oldQuincIn=1;
00872             if (quincStart==0){
00873                 oldQuincTimeSD = (double) quincTimeSD.read_ms();
00874                 quincTime.reset();
00875                 quincTimeSD.reset();
00876                 quincStart=1;
00877             }
00878         }
00879         if(quincClock==false){
00880             oldQuincIn=0;
00881         }
00882     #else
00883         if ((((quinconceActive==0)&&(quincClock==true))||((quinconceActive==1)&&(quincClock==false)))&&(oldQuincIn==0)){
00884             oldQuincIn=1;
00885             if (quincStart==0){
00886                 oldQuincTimeSD = (double) quincTimeSD.read_ms();
00887                 quincTime.reset();
00888                 quincStart=1;
00889             }
00890         }
00891         if (quinconceActive==0){
00892             if (quincClock==false){
00893                 oldQuincIn=0;
00894             }
00895         }else{
00896             if (quincClock==true){
00897                 oldQuincIn=0;
00898             }
00899         }
00900     #endif
00901     //****************************************************************************************
00902     if (quincCnt>=4){
00903         if (countPicks==0){
00904             if ((sincroQui==1)&&(quincStart==0)){
00905                 // decelera
00906                 countPicks=1;
00907             }
00908             if ((sincroQui==0)&&(quincStart==1)){
00909                 // accelera
00910                 countPicks=2;
00911             }
00912         }
00913         if ((sincroQui==1)&&(quincStart==1)){
00914             if (countPicks==1){   //decelera
00915                 scostamento = oldQuincTimeSD;
00916                 if (scostamento < (tempoBecchiPerQuinc*0.75f)){
00917                     double scostPerc = (scostamento/tempoBecchiPerQuinc);
00918                     percento -= ((double)quincPIDminus/100.0f)*(scostPerc);
00919                     #if defined(pcSerial)
00920                         #if defined(laq)
00921                             pc.printf("RALL scos2: %f tbpq: %f percento: %f \n",scostamento,tempoBecchiPerQuinc,percento);
00922                         #endif
00923                     #endif
00924                 }
00925                 //if (scostamento <15.0f){percento=0.0f;}
00926             }
00927             if (countPicks==2){   //accelera
00928                 scostamento = (double)quincTime.read_ms();
00929                 if (scostamento < (tempoBecchiPerQuinc*0.75f)){
00930                     double scostPerc = (scostamento/tempoBecchiPerQuinc);
00931                     percento += ((double)quincPIDplus/100.0f)*(scostPerc);
00932                     #if defined(pcSerial)
00933                         #if defined(laq)
00934                             pc.printf(
00935                             "ACCE scos1: %f tbpq: %f percento: %f \n",scostamento,tempoBecchiPerQuinc,percento);
00936                         #endif
00937                     #endif
00938                 }
00939                 //if (scostamento <15.0f){percento=0.0f;}
00940             }
00941             sincroQui=0;
00942             quincStart=0;
00943             countPicks=0;
00944             #if !defined(speedMaster)
00945                 if (quincCnt>=3){
00946                         if (speedFromMaster>0.0f){
00947                             if (enableSimula==0){
00948                                 tractorSpeed_MtS_timed = speedFromMaster + percento;
00949                             }
00950                         }
00951                 }
00952             #endif
00953         }
00954         
00955         //*******************************************************************
00956         if (canDataCheckEnable==true){        
00957             if (canDataCheck==1){   // sincro da comunicazione can del valore di posizione del tamburo master
00958                 canDataCheck=0;
00959                 double parametro = SDsectorStep/3.0f;
00960                 double differenza=0.0f;
00961                 #if defined(mezzo)
00962                     if (quinconceActive==1){
00963                         differenza = (double)masterSinc - (double)prePosSD;
00964                     }else{
00965                         differenza = (double)mast2_Sinc - (double)prePosSD;
00966                     }
00967                 #else
00968                     differenza = (double)mast2_Sinc - (double)prePosSD;
00969                 #endif
00970                 if ((differenza > 0.0f)&&(differenza < parametro)){
00971                     double diffPerc = differenza / parametro; 
00972                     percento += ((double)quincPIDplus/100.0f)*abs(diffPerc);
00973                     #if defined(pcSerial)
00974                         #if defined(quinca)
00975                             pc.printf("m1 %d m2 %d prePo %d diffe %f perce %f parm %f %\n",masterSinc, mast2_Sinc,prePosSD,differenza,percento, parametro);
00976                         #endif
00977                     #endif
00978                 }
00979                 if ((differenza < 0.0f)&&(abs(differenza) < parametro)){
00980                     double diffPerc = (double)differenza / parametro; 
00981                     percento -= ((double)quincPIDminus/100.0f)*abs(diffPerc);
00982                     #if defined(pcSerial)
00983                         #if defined(quinca)
00984                             pc.printf("m1 %d m2 %d prePo %d diffe %f perce %f parm %f %\n",masterSinc, mast2_Sinc,prePosSD,differenza,percento, parametro);
00985                         #endif
00986                     #endif
00987                 }
00988 
00989                 #if !defined(speedMaster)
00990                     if (quincCnt>=3){
00991                             if (speedFromMaster>0.0f){
00992                                 if (enableSimula==0){
00993                                     tractorSpeed_MtS_timed = speedFromMaster + percento;
00994                                 }
00995                             }
00996                     }
00997                 #endif
00998             }
00999         }
01000         
01001     }
01002     if ((percento) > ((double) quincLIMplus/100.0f)){
01003         percento= (double)quincLIMplus/100.0f;
01004     }
01005     if ((percento) < (((double)quincLIMminus*-1.0f)/100.0f)){
01006         percento=((double)quincLIMminus*-1.0f)/100.0f;
01007     }
01008 }
01009 // ----------------------------------------  
01010 #if defined(seedSensor)
01011     void resetDelay(){
01012         delaySeedCheck.reset();
01013         delaySeedCheck.stop();
01014     }
01015 #endif
01016 // ------------------------------------------------------------------------------------------------------------------------------------------------------------------
01017 // MAIN SECTION
01018 // ---------------------------------------------------------------------------------------------------------------------------------------------------------------
01019 
01020 int main()
01021 {
01022     //wait(1.0f);
01023     wd.Configure(2);  //watchdog set at xx seconds
01024     
01025     stepSetting();
01026     
01027     for (int a=0; a<5;a++){
01028         mediaSpeed[a]=0;
01029     }
01030     
01031     
01032     // DC reset ad set
01033     int decima = 100;
01034     wait_ms(200);
01035     SD_CurrentStart=floor(SDcurrent.read()*decima)/decima;
01036     wait_ms(2);
01037     SD_CurrentStart+=floor(SDcurrent.read()*decima)/decima;
01038     wait_ms(1);
01039     SD_CurrentStart+=floor(SDcurrent.read()*decima)/decima;
01040     wait_ms(3);
01041     SD_CurrentStart+=floor(SDcurrent.read()*decima)/decima;
01042     SD_CurrentStart=(floor((SD_CurrentStart/4.0f)*decima)/decima)-0.01f; 
01043     wait_ms(100);
01044     DC_prepare();
01045     
01046     speedTimer.start();                        // speed pulse timer 
01047     intraPickTimer.start();
01048     speedTimeOut.start();               
01049     speedFilter.start();
01050     seedFilter.start();
01051     TBfilter.start();
01052     sincroTimer.start();
01053     rotationTimeOut.start();
01054     metalTimer.start();
01055     quincTime.start();
01056     quincTimeSD.start();
01057     //intraEncoTimer.start();
01058     
01059     //*******************************************************
01060     // controls for check DC motor current
01061     pwmCheck.rise(&startDelay);
01062     
01063     if (inProva==0){
01064         tractorSpeedRead.rise(&tractorReadSpeed);
01065         #if !defined(speedMaster)
01066             quinconceIn.rise(&quincTrigon);
01067             quinconceIn.fall(&quincTrigof);
01068         #endif
01069         #if defined(speedMaster)
01070             tftUpdate.attach(&videoUpdate,0.50f);
01071         #endif
01072         seedCorrection.attach(&seedCorrect,0.005f); // con 16 becchi a 4,5Kmh ci sono 37mS tra un becco e l'altro, quindi 8 correzioni di tb
01073         dcSetting();
01074         #if defined(seedSensor)
01075             seedCheck.fall(&seedSensorTask);
01076         #endif
01077     }else{
01078       tftUpdate.attach(&videoUpdate,0.125f);
01079     }        
01080     
01081     aggiornaParametri();
01082 
01083     SDmotorPWM.period_us(periodoSD);      // frequency 1KHz pilotaggio motore DC
01084     SDmotorPWM.write(1.0f);         // duty cycle = stop
01085     TBmotorDirecti=1;               // tb motor direction set
01086 
01087     #if defined(provaStepper)
01088        TBmotorRst=0;
01089        TBticker.attach_us(&step_TBPulseOut,1000.0f);  // clock time are seconds and attach seed motor stepper controls
01090     #endif // end prova stepper
01091     
01092     #if defined(canbusActive)
01093         can1.attach(&leggiCAN, CAN::RxIrq);
01094     #endif
01095     
01096 //**************************************************************************************************************
01097 // MAIN LOOP
01098 //**************************************************************************************************************
01099     while (true){
01100         // ripetitore segnale di velocità
01101         if (tractorSpeedRead==0){speedClock=0;}
01102         
01103         // inversione segnali ingressi
01104         #if !defined(simulaBanco)
01105             seedWheelZeroPinInput = !seedWheelZeroPinInputRev;
01106         #else
01107             if ((prePosSD-500) >= SDsectorStep){
01108                 seedWheelZeroPinInput=1;
01109             }
01110             if ((prePosSD > 500)&&(prePosSD<580)){
01111                 seedWheelZeroPinInput=0;
01112             }
01113         #endif    
01114         TBzeroPinInput = !TBzeroPinInputRev;
01115         
01116         // se quinconce attivo ed unita' master invia segnale di sincro
01117         #if defined(speedMaster)
01118             if (seedWheelZeroPinInput==1){
01119                 quinconceOut=0;
01120             }
01121             if (((double)(prePosSD-500) >= (SDsectorStep/((double)quincSector)))&&(quinconceOut=1)){
01122                 quinconceOut=1;
01123             }
01124             if (quinconceActive==1){
01125                 if ((quinconceOut==1)&&(oldQuinconceOut==1)){
01126                     posForQuinc=500;
01127                     oldQuinconceOut=0;
01128                 }
01129                 if (((double)posForQuinc-500.0f)> (SDsectorStep-200)){
01130                     oldQuinconceOut=1;
01131                 }
01132             }                    
01133         #endif
01134 
01135         #if defined(overWriteCanSimulation)
01136             leggiCAN();
01137         #endif
01138 
01139         // simulazione velocita
01140         if (enableSimula==1){
01141             double TMT = 0.0f;
01142             if (speedSimula > 0){
01143                 TMT = (double)(speedSimula) * 100.0f /3600.0f;
01144                 pulseSpeedInterval = pulseDistance / TMT;
01145             }else{
01146                 pulseSpeedInterval = 10000.0f;
01147             }                
01148             if (avviaSimula==1){
01149                 if(oldSimulaSpeed!=pulseSpeedInterval){
01150                     #if defined(pcSerial)
01151                         #if defined(canDataReceived)
01152                             pc.printf("Pulseinterval %f \n",pulseSpeedInterval);
01153                         #endif
01154                     #endif
01155                     spedSimclock.attach_us(&speedSimulationClock,pulseSpeedInterval);
01156                     oldSimulaSpeed=pulseSpeedInterval;
01157                 }
01158             }else{
01159                 oldSimulaSpeed=10000.0f;
01160                 spedSimclock.detach();
01161             }
01162         }else{
01163             spedSimclock.detach();
01164         }
01165         
01166         //*******************************************************
01167         // determina se sono in bassa velocità per il controllo di TB
01168         if (speedOfSeedWheel<=minSeedSpeed){
01169             if (lowSpeedRequired==0){
01170                 ritardaLowSpeed.reset();
01171                 ritardaLowSpeed.start();
01172             }
01173             lowSpeedRequired=1;
01174         }else{
01175             if (lowSpeedRequired==1){
01176                 lowSpeedRequired=0;
01177                 ritardaLowSpeed.reset();
01178                 ritardaLowSpeed.stop();
01179             }
01180         }
01181 
01182         if (ritardaLowSpeed.read_ms()> 2000){
01183             lowSpeed=1;
01184         }else{
01185             lowSpeed=0;
01186         }
01187         
01188 
01189 //**************************************************************************************************************
01190 //**************************************************************************************************************
01191 // LOGICAL CONTROLS
01192 //**************************************************************************************************************
01193 //**************************************************************************************************************
01194         
01195         if (inProva==0){
01196             if ((startCycleSimulation==0)&&(enableSimula==0)){
01197                 zeroRequestBuf=1;
01198                 runRequestBuf=0;
01199                 enableCycle=1;  
01200             }else{
01201                 zeroRequestBuf=1;
01202                 runRequestBuf=0;
01203                 enableCycle=1;
01204             }
01205             if ((tractorSpeedRead==0)&&(speedFilter.read_ms()>3)){
01206                 oldTractorSpeedRead=0;
01207             }
01208             // ----------------------------------------
01209             // filtra il segnale dei becchi per misurare il tempo di intervallo tra loro
01210             // ----------------------------------------
01211             if ((seedWheelZeroPinInput==0)&&(oldSeedWheelZeroPinInput==1)){
01212                 if(seedFilter.read_ms()>=4){
01213                     oldSeedWheelZeroPinInput=0;
01214                     SDzeroDebounced=0;
01215                 }
01216             }
01217             if ((seedWheelZeroPinInput==1)&&(oldSeedWheelZeroPinInput==0)){
01218                 timeIntraPick = (double)intraPickTimer.read_ms();
01219                 prePosSD=500; // preposizionamento SD
01220                 intraPickTimer.reset();
01221                 rotationTimeOut.reset();
01222                 seedFilter.reset();          
01223                 sincroTimer.reset();
01224                 oldSeedWheelZeroPinInput=1;
01225                 quincTime.reset();
01226                 quincTimeSD.reset();
01227                 SDzeroDebounced=1;
01228                 sincroQui=1;
01229                 SDwheelTimer.reset();
01230                 #if defined(speedMaster)
01231                     if (quinconceActive==0){
01232                         posForQuinc=500;
01233                     }
01234                 #endif
01235                 if (quincCnt<10){
01236                     quincCnt++;
01237                 }
01238                 if ((aspettaStart==0)&&(lowSpeed==1)){
01239                     beccoPronto=1;
01240                 }
01241                 SDzeroCyclePulse=1;
01242                 lockStart=0;
01243                 double fase1=0.0f;
01244                 forzaFase=0;
01245                 double limite=fixedStepGiroSD/pickNumber;
01246                 if (tamburoStandard==0){
01247                     fase1=TBdeltaStep;  
01248                 }else{
01249                     if(speedForCorrection >= speedOfSeedWheel){
01250                         fase1=TBdeltaStep;
01251                     }else{
01252                         //fase1=(TBdeltaStep)-(((speedOfSeedWheel-speedForCorrection)/maxWorkSpeed)*(TBfaseStep));
01253                         fase1=(TBdeltaStep)-(((speedOfSeedWheel)/maxWorkSpeed)*(TBfaseStep));
01254                     }
01255                     if (fase1 > limite){
01256                         fase1 -= limite;    // se la fase calcolata supera gli step del settore riporta il valore nell'arco precedente (es. fase 1 800, limite 750, risulta 50)
01257                         //forzaFase=1;
01258                     }
01259                     if ((fase1 > (limite -20.0f))&&(fase1<(limite +5.0f))){
01260                         fase1 = limite -20.0f;  // se la fase è molto vicina al limite interpone uno spazio minimo di lavoro del sincronismo
01261                         forzaFase=1;
01262                     }
01263                     trigRepos=1;
01264                 }
01265                 fase = (uint32_t)fase1+500;
01266                 #if defined(pcSerial)
01267                     #if defined(inCorre)
01268                         pc.printf(" limite %f", limite);
01269                         pc.printf(" delta %f", TBdeltaStep);
01270                         pc.printf(" faseStep %f", TBfaseStep);
01271                         pc.printf(" fase %d",fase);
01272                         pc.printf(" forzaFase %d",forzaFase);
01273                         pc.printf(" trigRepos %d", trigRepos);
01274                         pc.printf(" ActualSD: %d",SDactualPosition);
01275                         pc.printf(" SpeedWheel: %f",speedOfSeedWheel);
01276                         pc.printf(" SPEED: %f \n",tractorSpeed_MtS_timed);
01277                     #endif
01278                 #endif
01279                 if (timeIntraPick >= (memoIntraPick*2)){
01280                     if ((aspettaStart==0)&&(zeroRequestBuf==0)){
01281                         if (firstStart==0){
01282                             all_pickSignal=1;
01283                         }
01284                     }
01285                 }
01286                 memoIntraPick = timeIntraPick;
01287                 if ((speedFromPick==1)&&(encoder==false)){
01288                     speedOfSeedWheel=((seedPerimeter / pickNumber)/timeIntraPick)*1000.0f;
01289                     #if defined(pcSerial)
01290                         #if defined(Qnca)
01291                             pc.printf("perim: %f pickN: %f sped: %f\n", seedPerimeter, pickNumber,speedOfSeedWheel);
01292                         #endif
01293                     #endif
01294                 }
01295                 if (encoder==false){
01296                     pulseRised2=1;
01297                 }
01298                 #if defined(speedMaster)
01299                     if ((tractorSpeed_MtS_timed==0.0f)&&(zeroCycle==0)&&(zeroCycleEnd==1)){
01300                         if ((firstStart==0)&&(simOk==0)&&(enableSimula==0)&&(zeroCycleEnd==1)){
01301                             all_noSpeedSen=1;
01302                         }
01303                     }
01304                     double oldLastPr = (double)oldLastPulseRead*1.5f;
01305                     if((double)speedTimeOut.read_us()> (oldLastPr)){
01306                         if ((firstStart==0)&&(simOk==0)&&(enableSimula==0)&&(zeroCycleEnd==1)){
01307                             all_speedError =1;
01308                         }
01309                     }
01310                 #endif
01311                 //*******************************************
01312                 // esegue calcolo clock per la generazione della posizione teorica
01313                 // la realtà in base al segnale di presenza del becco
01314                 realSpeed = speedOfSeedWheel;
01315                 realGiroSD = seedPerimeter / realSpeed;
01316                 tempoBecco = (realGiroSD/360.0f)*16000.0f;
01317                 frequenzaReale = fixedStepGiroSD/realGiroSD;
01318                 semiPeriodoReale = (1000000.0f/frequenzaReale);
01319                 tempoTraBecchi_mS = 0.0f;
01320                 seedWheelRPM = (speedOfSeedWheel)*K_WheelRPM ;                      // calcola i giri al minuto della ruota di semina           7.37                31,75
01321                 TBrpm = seedWheelRPM*rapportoRuote;                                 // 5.896                                                                        31,75
01322                 TBfrequency = (TBrpm*K_TBfrequency);                                // 130Hz a 0,29Mts                                                            1397,00 a 1,25mt/s con 15 becchi e 15 celle
01323                 TBperiod=1000000.0f/TBfrequency;                                    //                                                                              715uS
01324             }
01325 // ----------------------------------------
01326 // check SD fase 
01327             if ((prePosSD >= fase)||(forzaFase==1)){//&&(prePosSD < (fase +30))){
01328                 forzaFase=0;
01329                 if (trigRepos==1){
01330                     SDactualPosition=0;
01331                     if ((countCicli<30)&&(trigCicli==0)){countCicli++;trigCicli=1;}
01332                     if(countCicli>=cicliAspettaStart){aspettaStart=0;}
01333                     if ((lowSpeed==0)&&(aspettaStart==0)&&(lockStart==0)){syncroCheck=1;beccoPronto=0;}
01334                     if (trigTB==0){
01335                         inhibit=1;
01336                         trigSD=1;
01337                     }else{
01338                         inhibit=0;
01339                         trigTB=0;
01340                         trigSD=0;
01341                     }
01342                     trigRepos=0;
01343                 }
01344             }else{
01345                 trigCicli=0;
01346             }
01347 // ----------------------------------------  
01348 // filtra il segnale del tamburo per lo stop in fase del tamburo stesso
01349             if (TBzeroPinInput==0){if (TBfilter.read_ms()>=5){oldTBzeroPinInput=0;}}
01350             if ((TBzeroPinInput==1)&&(oldTBzeroPinInput==0)){
01351                 oldTBzeroPinInput=1;
01352                 if (loadDaCanInCorso==0){
01353                     stopCicloTB=1;
01354                     startCicloTB=0;
01355                 }
01356                 TBfilter.reset();
01357                 TBzeroCyclePulse=1;
01358                 TBactualPosition=0;
01359                 if (cellsCounterLow < 0xFF){
01360                     cellsCounterLow++;
01361                 }else{
01362                     cellsCounterHig++;
01363                     cellsCounterLow=0;
01364                 }
01365                 if (loadDaCanInCorso==1){
01366                     cntCellsForLoad++;
01367                     if (cntCellsForLoad >= 5){
01368                         stopCicloTB=1;   
01369                         cntCellsForLoad=0;
01370                     }
01371                 }else{
01372                     cntCellsForLoad=0;
01373                 }
01374                 if (trigSD==0){
01375                     inhibit=1;
01376                     trigTB=1;
01377                 }else{
01378                     inhibit=0;
01379                     trigTB=0;
01380                     trigSD=0;
01381                 }
01382                 // torna indietro per sbloccare il tamburo
01383                 if ((TBmotorDirecti==0)&&(erroreTamburo==1)){
01384                     cntCellsForReload++;
01385                     if (cntCellsForReload >= cellsCountSet){
01386                         TBmotorDirecti=1;
01387                         erroreTamburo=0;
01388                     }    
01389                 }
01390                 #if defined(seedSensor)
01391                     resetDelay();
01392                     delaySeedCheck.start();
01393                 #endif
01394             }
01395             if ((double)TBactualPosition > ((TBgiroStep/cellsNumber)*1.2f)){
01396                 if (firstStart==0){
01397                     if (cntTbError>2){
01398                         all_cellSignal=1;
01399                         #if defined(seedSensor)
01400                             resetDelay();
01401                         #endif
01402                     }
01403                 }
01404                 if (erroreTamburo==0){
01405                     erroreTamburo=1;
01406                     TBmotorDirecti=0;
01407                     cntCellsForReload=0;
01408                     cntTbError++;
01409                     #if defined(seedSensor)
01410                         resetDelay();
01411                     #endif
01412                 }
01413             }
01414             if (((double)TBactualPosition > ((TBgiroStep/cellsNumber)*3.0f))||(cntTbError>4)){
01415                 if (firstStart==0){
01416                     all_noStepRota=1;
01417                     #if defined(seedSensor)
01418                         resetDelay();
01419                     #endif
01420                 }
01421                 cntTbError=0;
01422             }
01423 // ----------------------------------------            
01424 // read and manage joystick
01425             // WARNING - ENABLE CYCLE IS SOFTWARE ALWAYS ACTIVE
01426             if (enableCycle==1){
01427                 if(runRequestBuf==1){
01428                     if (OldStartCycle!=runRequestBuf){
01429                         if((startCycle==0)&&(zeroCycleEnd==1)){
01430                             startCycle=1;
01431                             OldStartCycle = runRequestBuf;
01432                             oldZeroCycle=0;
01433                         }
01434                     }
01435                 }else{
01436                     startCycle=0;
01437                     pntMedia=0;
01438                 }
01439                 if (azzeraDaCan==1){
01440                     if (tractorSpeed_MtS_timed==0.0f){
01441                         zeroRequestBuf=1;
01442                         oldZeroCycle=0;
01443                     }
01444                     azzeraDaCan=0;
01445                 }
01446                 if (loadDaCan==1){
01447                     if (tractorSpeed_MtS_timed==0.0f){
01448                         ciclaTB();
01449                     }                    
01450                 }
01451                 if ((zeroRequestBuf==1)){
01452                     if (oldZeroCycle!=zeroRequestBuf){
01453                         zeroCycle=1;
01454                         zeroCycleEnd=0;
01455                         SDzeroed=0;
01456                         TBzeroed=0;
01457                         zeroTrigger=0;
01458                         oldZeroCycle = zeroRequestBuf;
01459                     }
01460                 }
01461             }else{
01462                 startCycle=0;
01463                 zeroCycle=0;
01464             }
01465             
01466     //***************************************************************************************************        
01467     // pulseRised define the event of speed wheel pulse occurs
01468     //        
01469             double maxInterval = pulseDistance/minWorkSpeed;
01470             double minIntervalPulse = pulseDistance/maxWorkSpeed;
01471             if (pulseRised==1){ 
01472                 if (enableSpeed<10){enableSpeed++;}
01473                 pulseRised=0;
01474                 pulseRised1=1;
01475                 speedMediaCalc();
01476                 // calcola velocità trattore
01477                 if(enableSpeed>=2){
01478                     if ((pulseSpeedInterval>=0.0f)){ //minIntervalPulse)&&(pulseSpeedInterval<maxInterval)){
01479                         if((quincCnt<3)||(speedFromMaster==0.0f)||(enableSimula==1)){
01480                             tractorSpeed_MtS_timed = ((pulseDistance  / pulseSpeedInterval));  // tractor speed (unit= Mt/S) from pulse time interval
01481                         }
01482                         /*#if !defined(speedMaster)
01483                             if (quincCnt>=5){
01484                                     if (speedFromMaster>0.0f){
01485                                         tractorSpeed_MtS_timed = speedFromMaster + percento;
01486                                     }
01487                             }
01488                         #endif*/
01489                         if (checkSDrotation==0){
01490                             checkSDrotation=1;
01491                             SDwheelTimer.start();
01492                         }
01493                     }
01494                 }
01495                 speedTimeOut.reset();
01496             }else{
01497                 double oldLastPr = (double)oldLastPulseRead*1.7f;
01498                 if((double)speedTimeOut.read_us()> (oldLastPr)){
01499                     tractorSpeed_MtS_timed = 0.0f;
01500                     #if defined(seedSensor)
01501                         resetDelay();
01502                     #endif
01503                     pntMedia=0;
01504                     speedTimeOut.reset();
01505                     enableSpeed=0;
01506                     quincCnt=0;
01507                 }
01508             }
01509             
01510             #if defined(seedSensor)
01511                 if (seedSensorEnable==true){
01512                     if (delaySeedCheck.read_ms()>100){
01513                         if (seedSee==0){
01514                             all_noSeedOnCe=1;
01515                         }
01516                         resetDelay();
01517                     }
01518                 }
01519             #endif
01520             // esegue il controllo di velocità minima
01521             /*if ((double)speedTimer.read_ms()>=maxInterval){
01522                 tractorSpeed_MtS_timed = 0.0f;
01523                 enableSpeed=0;
01524             }*/
01525             // esegue il controllo di velocità massima
01526             /*if ((double)speedTimer.read_ms()<=minIntervalPulse){
01527                 tractorSpeed_MtS_timed = 4.5f;
01528             }*/
01529     //***************************************************************************************************************
01530     // cycle logic control section
01531     //***************************************************************************************************************
01532                 if (enableSimula==1){if(simOk==0){tractorSpeed_MtS_timed=0.0f;}}
01533                 if ((tractorSpeed_MtS_timed>0.01f)){
01534                     cycleStopRequest=1;
01535                     // calcola il tempo teorico di passaggio becchi sulla base della velocità del trattore
01536                     tempoGiroSD = seedPerimeter / tractorSpeed_MtS_timed;        // tempo Teorico impiegato dalla ruota di semina per fare un giro completo (a 4,5Km/h impiega 1,89 secondi) 
01537                     if (encoder==false){
01538                         if (speedFromPick==1) {
01539                             tempoTraBecchi_mS = (tempoGiroSD / pickNumber)*1000.0f;      // tempo tra due impulsi dai becchi in millisecondi ( circa 157mS a 4,5Km/h)  
01540                         }else{
01541                             tempoTraBecchi_mS = (tempoGiroSD / 25.0f)*1000.0f;      // tempo tra due impulsi dai becchi in millisecondi ( circa 157mS a 4,5Km/h)  
01542                         }
01543                     }else{
01544                         tempoTraBecchi_mS = (tempoGiroSD / (SDreductionRatio*25.5f))*1000.0f;      // tempo tra due impulsi dai becchi in millisecondi ( circa 157mS a 4,5Km/h)  
01545                         double pippo=0.0f;
01546                         #if !defined(speedMaster)
01547                             pippo = seedPerimeter / speedFromMaster;
01548                         #endif
01549                         tempoBecchiPerQuinc = (pippo / pickNumber)*1000.0f;
01550                     }
01551                     //*******************************************
01552                     // segue calcolo duty cycle comando motore DC per allinearsi con la velocità del trattore
01553                     double dutyTeorico = 0.00;
01554                     if ((tractorSpeed_MtS_timed>0.0)&&(tractorSpeed_MtS_timed<tabSpeed[0])){dutyTeorico = tabComan[0];}
01555                     for (int ii = 0;ii<16;ii++){
01556                         if ((tractorSpeed_MtS_timed>=tabSpeed[ii])&&(tractorSpeed_MtS_timed<tabSpeed[ii+1])){
01557                             dutyTeorico = tabComan[ii+1];
01558                         }
01559                     }
01560                     if (tractorSpeed_MtS_timed > tabSpeed[16]){dutyTeorico=tractorSpeed_MtS_timed/maxWorkSpeed;}
01561                     #if !defined(speedMaster)
01562                         quinCalc();
01563                     #endif
01564                     if ((enableSpeed>3)&&(pulseRised2==1)&&(quincCnt>=2)){
01565                         double erroreTempo = 0.0f;
01566                         if(encoder==false){
01567                             if(speedFromPick==1){
01568                                 erroreTempo = (double)timeIntraPick - tempoTraBecchi_mS;
01569                             }else{
01570                                 erroreTempo = (double)memoTimeHole - tempoTraBecchi_mS;             // errore tra il tempo previsto ed il tempo reale ( >0 se sto andando più piano del previsto)
01571                             }
01572                         }else{
01573                             erroreTempo = ((double)memoTimeHole/1000.0f) - tempoTraBecchi_mS;             // errore tra il tempo previsto ed il tempo reale ( >0 se sto andando più piano del previsto)
01574                         }
01575                         double errorePercentuale = erroreTempo / tempoTraBecchi_mS;
01576                         double k3=0.0f;
01577                         double k4=0.0f;
01578                         double k5=0.0f;
01579                         double k6=0.0f;
01580                         /*if (tractorSpeed_MtS_timed <= minSeedSpeed){
01581                             k3=1.030f;
01582                             k4=5.103f;
01583                             k5=10.00f;
01584                             k6=20.50f;
01585                         }else{*/
01586                             #if defined(speedMaster)
01587                                 k3=0.010f;
01588                             #else
01589                                 k3=0.050f;
01590                             #endif
01591                             k4=1.103f;
01592                             k5=10.00f;
01593                             k6=20.50f;
01594                         //}
01595                         double L1 = 0.045f;
01596                         double L_1=-0.045f;
01597                         double L2 = 0.150f;
01598                         double L_2=-0.150f;
01599                         double L3 = 0.301f;
01600                         double L_3=-0.301f;
01601                         double k1=0.0f;
01602                         if ((errorePercentuale > L3)||(errorePercentuale < L_3)){
01603                             k1=errorePercentuale*k6;
01604                         }
01605                         if (((errorePercentuale >= L2)&&(errorePercentuale<=L3))||((errorePercentuale <= L_2)&&(errorePercentuale>=L_3))){
01606                             k1=errorePercentuale*k5;
01607                         }
01608                         if (((errorePercentuale < L2)&&(errorePercentuale>L1))||((errorePercentuale > L_2)&&(errorePercentuale<L_1))){
01609                             k1=errorePercentuale*k4;
01610                         }
01611                         if ((errorePercentuale < L1)||(errorePercentuale > L_1)){
01612                             k1=errorePercentuale*k3;
01613                         }
01614                         double memoCorrezione = k1;
01615                         if (quincCnt >= 2){
01616                             correzione = correzione + memoCorrezione;
01617                             if (correzione > (1.0f - dutyTeorico)){correzione = (1.0f - dutyTeorico);}
01618                             if ((correzione < 0.0f)&&(dutyTeorico+correzione<0.0f)){correzione = -1.0f*dutyTeorico;}
01619                         }
01620                         pulseRised1=0;
01621                         pulseRised2=0;
01622                         #if defined(pcSerial)
01623                             #if defined(Qnca)
01624                                 pc.printf("ErTem: %f K1: %f Corr: %f MemoCorr:%f DutyTeo: %f \n",erroreTempo, k1,correzione, memoCorrezione, dutyTeorico);
01625                                 pc.printf("TsP: %f SpW: %f InPic: %f  TBec: %f EPerc: %f Duty:%f \n",tractorSpeed_MtS_timed,speedOfSeedWheel,timeIntraPick, tempoTraBecchi_mS,errorePercentuale, dcActualDuty);
01626                             #endif
01627                         #endif
01628                         #if defined(pcSerial)
01629                             #if defined(Qncb)
01630                                 pc.printf("TsP: %f SpW: %f InPic: %f   EPerc: %f Duty:%f \n",tractorSpeed_MtS_timed,speedOfSeedWheel,timeIntraPick, errorePercentuale, dcActualDuty);
01631                             #endif
01632                         #endif
01633                     }
01634                     // introduce il controllo di corrente
01635                     if (currentCheckEnable==true){
01636                         if (incrementCurrent){
01637                             boostDcOut +=0.005f;
01638                         }
01639                         if (reduceCurrent){
01640                             boostDcOut -=0.005f;
01641                         }
01642                         if (boostDcOut >= 0.2f){
01643                             boostDcOut=0.2f;
01644                             all_genericals=1;
01645                         }
01646                         if (boostDcOut <=-0.2f){
01647                             boostDcOut=-0.2f;
01648                             all_genericals=1;
01649                         }   
01650                         correzione += boostDcOut;
01651                     }
01652                     DC_brake=0;
01653                     DC_forward=1;
01654                     DC_prepare();
01655 
01656                     // il semiperiodoreale è calcolato sulla lettura del passaggio becchi reale
01657                     seedWheelPeriod = semiPeriodoReale;
01658                     if (seedWheelPeriod < 180.0f){seedWheelPeriod = 180.0f;}
01659                     if ((oldSeedWheelPeriod!=seedWheelPeriod)&&(seedWheelPeriod >=180.0f )){
01660                         SDticker.attach_us(&step_SDPulseOut,seedWheelPeriod);  // clock time are milliseconds and attach seed motor stepper controls
01661                         oldSeedWheelPeriod=seedWheelPeriod;
01662                     }
01663 
01664                     if((quincCnt>=3)){
01665                         if (correzioneAttiva==1){
01666                             dcActualDuty = dutyTeorico + correzione;
01667                         }else{
01668                             dcActualDuty = dutyTeorico;
01669                         }
01670                     }else{
01671                         dcActualDuty = dutyTeorico;
01672                     }
01673                     if (dcActualDuty <=0.0f){dcActualDuty=0.05f;}
01674                     if (dcActualDuty > 0.95f){dcActualDuty = 0.95f;}//dcMaxSpeed;}
01675                     if (olddcActualDuty!=dcActualDuty){
01676                         SDmotorPWM.write(1.0f-dcActualDuty);
01677                         olddcActualDuty=dcActualDuty;
01678                     }
01679                     // allarme
01680                     if (SDwheelTimer.read_ms()>4000){
01681                         if (firstStart==0){
01682                             all_noDcRotati=1;
01683                         }
01684                         #if defined(pcSerial)
01685                             #if defined(VediAllarmi)
01686                                 pc.printf("allarme no DC rotation");
01687                             #endif
01688                         #endif
01689                         
01690                     }
01691 
01692     //***************************************************************************************************************
01693     // CONTROLLA TAMBURO
01694     //***************************************************************************************************************
01695                     if(lowSpeed==0){
01696                         if (syncroCheck==1){
01697                             syncroCheck=0;
01698                             lockStart=1;
01699                             periodo = TBperiod;
01700                             if (aspettaStart==0){cambiaTB(periodo);}
01701                         }
01702                         // controllo di stop
01703                         double memoIntraP = (double)memoIntraPick*1.8f;
01704                         if ((double)rotationTimeOut.read_ms()> (memoIntraP)){
01705                             syncroCheck=0;
01706                             aspettaStart=1;
01707                             countCicli=0;
01708                             if (TBzeroCyclePulse==1){TBticker.detach();}
01709                         }
01710                     }else{  // fine ciclo fuori da low speed
01711                         syncroCheck=0;
01712                         lockStart=0;
01713                         if (beccoPronto==1){
01714                             if (tamburoStandard==1){
01715                                 double ritardoMassimo = 0.0f;
01716                                 if (encoder==false){
01717                                     if(speedFromPick==1){
01718                                         ritardoMassimo = (double)timeIntraPick;
01719                                     }else{
01720                                         ritardoMassimo = (double)memoTimeHole;
01721                                     }
01722                                 }else{
01723                                     ritardoMassimo = (double)timeIntraPick;
01724                                 }
01725                                 int tempoDiSincro = (int)((double)(ritardoMassimo - ((tempoBecco/2.0f)+((speedOfSeedWheel/maxWorkSpeed)*ritardoMassimo))));         //
01726                                 if (tempoDiSincro <= 1){tempoDiSincro=1;}                                
01727                                 if ((sincroTimer.read_ms()>= tempoDiSincro)){
01728                                     if (tractorSpeed_MtS_timed >= minWorkSpeed){startCicloTB=1;}
01729                                     beccoPronto=0;
01730                                 }
01731                             }else{
01732                                 // tamburo per zucca
01733                                 if (speedOfSeedWheel >= minWorkSpeed){startCicloTB=1;}
01734                                 beccoPronto=0;
01735                             }
01736                         }
01737                         ciclaTB();
01738                     }
01739                     //*************************************************************
01740                 }else{  // fine ciclo con velocita maggiore di 0
01741                     SDwheelTimer.stop();
01742                     SDwheelTimer.reset();
01743                     #if defined(seedSensor)
01744                         resetDelay();
01745                     #endif
01746                     checkSDrotation=0;
01747                     oldFaseLavoro=0;
01748                     aspettaStart=1;
01749                     countCicli=0;
01750                     startCycle=0;
01751                     oldSeedWheelPeriod=0.0f;
01752                     oldPeriodoTB=0.0f;
01753                     correzione=0.0f;
01754                     OLDpulseSpeedInterval=1000.01f;
01755                     cicloTbinCorso=0;
01756                     cntTbError=0;
01757                     if (cycleStopRequest==1){
01758                         zeroDelay.reset();
01759                         zeroDelay.start();
01760                         runRequestBuf=0;
01761                         zeroRequestBuf=1;
01762                         cycleStopRequest=0;
01763                         SDzeroCyclePulse=0;
01764                         TBzeroCyclePulse=0;
01765                         zeroCycleEnd=0;
01766                         zeroCycle=1;
01767                         zeroTrigger=0;
01768                         noSDzeroRequest=1;
01769                     }
01770                 }
01771     //*************************************************************************************************        
01772     // ciclo di azzeramento motori
01773             if ((zeroCycleEnd==0)&&(zeroCycle==1)){//&&(zeroDelay.read_ms()>10000)){
01774                 if (zeroTrigger==0){
01775                     TBticker.attach_us(&step_TBPulseOut,1000.0f);  // clock time are seconds and attach seed motor stepper controls
01776                     DC_forward=1;
01777                     DC_brake=1;
01778                     DC_prepare();
01779                     frenata=0;
01780                     zeroTrigger=1;
01781                     ritardoStop.reset();
01782                     ritardoComandoStop.reset();
01783                     ritardoComandoStop.start();
01784                     timeOutZeroSD.start();
01785                     quincTimeSet.reset();
01786                 }
01787                 int tempoFrenata=300;
01788                 if (((ritardoStop.read_ms()>tempoFrenata)&&(SDzeroDebounced==0))||(accensione==1)||(ritardoComandoStop.read_ms()>400)){
01789                     accensione=0;
01790                     avvicinamento=1;
01791                     avvicinamentoOn.reset();
01792                     avvicinamentoOn.start();
01793                     SDmotorPWM.write(1.0f-0.32f);      // duty cycle = 60% of power
01794                     DC_forward=1;
01795                     DC_brake=0;
01796                     DC_prepare();
01797                     ritardoComandoStop.reset();
01798                     ritardoComandoStop.stop();
01799                 }
01800                 if (avvicinamento==1){
01801                     if(avvicinamentoOn.read_ms()>300){
01802                         SDmotorPWM.write(1.0f-0.7f);
01803                         avvicinamentoOn.reset();
01804                         avvicinamentoOff.reset();
01805                         avvicinamentoOff.start();
01806                     }
01807                     if(avvicinamentoOff.read_ms()>100){
01808                         SDmotorPWM.write(1.0f-0.32f);
01809                         avvicinamentoOff.reset();
01810                         avvicinamentoOff.stop();
01811                         avvicinamentoOn.start();
01812                     }
01813                 }else{
01814                     avvicinamentoOn.stop();
01815                     avvicinamentoOff.stop();
01816                     avvicinamentoOn.reset();
01817                     avvicinamentoOff.reset();
01818                 }
01819                 if (frenata==0){
01820                     if (SDzeroCyclePulse==1){
01821                         SDticker.detach();
01822                         frenata=1;
01823                         quincTimeSet.reset();
01824                         quincTimeSet.start();
01825                         ritardoStop.start();
01826                         //ritardoComandoStop.reset();
01827                         //ritardoComandoStop.stop();
01828                     }
01829                 }else{
01830                     #if defined(mezzo)
01831                         if (quinconceActive==0){
01832                             if (SDzeroCyclePulse==1){
01833                                 avvicinamento=0;
01834                                 DC_brake=1;
01835                                 DC_prepare();
01836                                 SDzeroed=1;
01837                                 ritardoStop.reset();
01838                                 ritardoStop.stop();
01839                             }
01840                         }else{
01841                             if (quincTimeSet.read_ms()>700){
01842                                 avvicinamento=0;
01843                                 DC_brake=1;
01844                                 DC_prepare();
01845                                 SDzeroed=1;
01846                                 ritardoStop.reset();
01847                                 ritardoStop.stop();
01848                                 quincTimeSet.stop();
01849                             }
01850                         }
01851                     #else
01852                         if (SDzeroCyclePulse==1){
01853                             avvicinamento=0;
01854                             DC_brake=1;
01855                             DC_prepare();
01856                             SDzeroed=1;
01857                             ritardoStop.reset();
01858                             ritardoStop.stop();
01859                         }
01860                     #endif
01861                 }
01862                 // azzera tutto in time out
01863                 if ((timeOutZeroSD.read_ms()>=10000)||(noSDzeroRequest==1)){
01864                     if ((firstStart==0)&&(noSDzeroRequest==0)){
01865                         all_no_Zeroing=1;
01866                     }
01867                     avvicinamento=0;
01868                     DC_brake=1;
01869                     DC_prepare();
01870                     SDzeroed=1;
01871                     ritardoStop.reset();
01872                     ritardoStop.stop();
01873                     avvicinamentoOn.stop();
01874                     avvicinamentoOff.stop();
01875                     avvicinamentoOn.reset();
01876                     avvicinamentoOff.reset();
01877                     ritardoComandoStop.reset();
01878                     ritardoComandoStop.stop();
01879                     timeOutZeroSD.stop();
01880                     timeOutZeroSD.reset();
01881                     noSDzeroRequest=0;
01882                 }
01883                 if (TBzeroCyclePulse==1){
01884                     TBticker.detach();
01885                     TBzeroed=1;
01886                 }
01887                 if ((SDzeroed==1)&&(TBzeroed==1)){
01888                     avvicinamentoOn.stop();
01889                     avvicinamentoOff.stop();
01890                     ritardoComandoStop.stop();
01891                     ritardoStop.stop();
01892                     zeroCycleEnd=1;
01893                     zeroCycle=0;
01894                     zeroTrigger=0;
01895                     runRequestBuf=1;
01896                     zeroRequestBuf=0;
01897                     cycleStopRequest=0;
01898                     SDzeroed=0;
01899                     TBzeroed=0;
01900                     timeOutZeroSD.stop();
01901                     timeOutZeroSD.reset();
01902                 }
01903             }
01904     
01905 //*************************************************************************************************        
01906             if (enableCycle==0){
01907                 zeroTrigger=0;
01908                 SDmotorPWM=0;
01909                 SDmotorInA=0;
01910                 SDmotorInB=0;
01911             }
01912             SDzeroCyclePulse=0;
01913             TBzeroCyclePulse=0;
01914 //*************************************************************************************************        
01915         }else{//end ciclo normale
01916 //*************************************************************************************************        
01917 //      task di prova della scheda
01918 //*************************************************************************************************        
01919           #if defined(provaScheda)
01920             clocca++;
01921             //led = !led;
01922             //txMsg.clear();
01923             //txMsg << clocca;
01924             //test.printf("aogs \n");
01925             //if(can1.write(txMsg)){
01926                 #if defined(pcSerial)
01927                     pc.printf("Can write OK \n");
01928                 #endif
01929             //}
01930             switch (clocca){
01931                 case 1:
01932                     TBmotorStepOut=1;       // define step command for up down motor driver
01933                     break;
01934                 case 2:
01935                     SDmotorPWM=1;       // define step command for seeding whell motor driver
01936                     break;
01937                 case 3:
01938                     speedClock=1;              // define input of 
01939                     break;
01940                 case 4:
01941                     break;
01942                 case 5:
01943                     SDmotorInA=1;
01944                     SDmotorInB=0;
01945                     break;
01946                 case 6:
01947                     break;
01948                 case 7:
01949                     break;
01950                 case 8:
01951                     break;
01952                 case 9:
01953                     break;
01954                 case 10:
01955                     break;
01956                 case 11:
01957                     break;
01958                 case 12:
01959                     break;
01960                 case 13:
01961                     break;
01962                 case 14:
01963                     SDmotorPWM=1;            // power mosfet 2 command out
01964                     break;
01965                 case 15:
01966                     break;
01967                 case 16:
01968                 case 17:
01969                     break;
01970                 case 18:
01971                     TBmotorStepOut=0;       // define step command for up down motor driver
01972                     SDmotorPWM=0;           // define step command for seeding whell motor driver
01973                     speedClock=0;              // define input of 
01974                     SDmotorInA=0;
01975                     SDmotorInB=0;
01976                     SDmotorPWM=0;            // power mosfet 2 command out
01977                     break;                    
01978                 default:
01979                     clocca=0;
01980                     break;
01981             }
01982             wait_ms(100);
01983           #endif // end prova scheda
01984             
01985           #if defined(provaDC)
01986             int rampa=1000;
01987             int pausa=3000;
01988             switch (clocca){
01989                 case 0:
01990                     DC_brake=0;
01991                     DC_forward=1;
01992                     duty_DC+=0.01f;
01993                     if (duty_DC>=1.0f){
01994                         duty_DC=1.0f;
01995                         clocca=1;
01996                     }
01997                     wait_ms(rampa);
01998                     break;
01999                 case 1:
02000                     wait_ms(pausa*4);
02001                     clocca=2;
02002                     break;
02003                 case 2:
02004                     DC_brake=0;
02005                     DC_forward=1;
02006                     duty_DC-=0.01f;
02007                     if (duty_DC<=0.0f){
02008                         duty_DC=0.0f;
02009                         clocca=3;
02010                     }
02011                     wait_ms(rampa);
02012                     break;
02013                 case 3:
02014                     wait_ms(pausa);
02015                     clocca=4;
02016                     break;
02017                 case 4:
02018                     DC_brake=0;
02019                     DC_forward=1;
02020                     duty_DC+=0.01f;
02021                     if (duty_DC>=1.0f){
02022                         duty_DC=1.0f;
02023                         clocca=5;
02024                     }
02025                     wait_ms(rampa);
02026                     break;
02027                 case 5:
02028                     wait_ms(pausa);
02029                     clocca=6;
02030                     break;
02031                 case 6:
02032                     DC_brake=0;
02033                     DC_forward=1;
02034                     duty_DC-=0.01f;
02035                     if (duty_DC<=0.0f){
02036                         duty_DC=0.0f;
02037                         clocca=7;
02038                     }
02039                     wait_ms(rampa);
02040                     break;
02041                 case 7:
02042                     wait_ms(pausa);
02043                     clocca=0;
02044                     break;
02045                 default:
02046                     break;
02047             }
02048             if (oldDuty_DC != duty_DC){            
02049                 SDmotorPWM.write(1.0f-duty_DC);      // duty cycle = stop
02050                 oldDuty_DC=duty_DC;
02051                 DC_prepare();
02052             }
02053           #endif
02054         }//end  in prova
02055         wd.Service();       // kick the dog before the timeout
02056     } // end while
02057 }// end main
02058