Das hab ich nur weggelassen, damits nicht so viel zu lesen ist.
Code
PROGRAM Jalousie_v1;
{$NOSHADOW}
{ $WG} {global Warnings off}
Device = mega328p , VCC = 5;
{ $BOOTRST $03800} {Reset Jump to $03800}
DEFINE_FUSES
// Override_Fuses;
NoteBook = A;
COMport = USB;
LockBits0 = [];
FuseBits0 = [];
FuseBits1 = [];
FuseBits2 = [];
IMPORT SysTick , SerPort , PWMport1A , PWMport1B , ADCPort;
FROM System IMPORT;
DEFINE
ProcClock = 16000000; {Hertz}
SysTick = 10; {msec}
StackSize = $0064 , iData;
FrameSize = $0064 , iData;
SerPort = 31250 , Stop1 , parNone; {Baud, StopBits|Parity}
RxBuffer = 8 , iData;
TxBuffer = 8 , iData;
ADCchans = 8 , iData ;
ADCpresc = 16;
PWMres1 = 8; {bits}
PWMpresc1 = 1;
PWMmode1 = slow , positive;
IMPLEMENTATION
CONST
// Operation
Oeffnen : BYTE = 3;
Schliessen : BYTE = 2;
Stoppen : BYTE = 1;
Steht : BYTE = 0;
// Modus
Inaktiv : BYTE = 0;
Teach : BYTE = 3;
Work : BYTE = 4;
Error : BYTE = 1;
Heat : BYTE = 2;
// Midi Commands
M_noteon : BYTE = $90;
M_noteoff : BYTE = $80;
M_press : BYTE = $A0;
M_cchange : BYTE = $B0;
M_pchange : BYTE = $C0;
//Tastenoffset 1. Ton = 36 (1+35)
M_offset : BYTE = 35;
M_warteauf_Cmd : BYTE = 0;
M_warteauf_CC : BYTE = 1;
M_warteauf_VV : BYTE = 2;
{$EEPROM}
STRUCTCONST
EE_accpoint : WORD = 220;
EE_ACC : WORD = 10;
EE_Decpoint : WORD = 100;
EE_dec : WORD = 10;
EE_Accdelay : WORD = 5;
EE_Decdelay : WORD = 10;
EE_SpeedMax : WORD = 255;
EE_SpeedHigh : WORD = 191;
EE_SpeedLow : WORD = 127;
EE_SpeedTeach : WORD = 127;
EE_Maxspeed_ab : WORD = 300;
EE_Highspeed_ab : WORD = 150;
EE_ADCPos_zu : WORD = 10;
EE_ADCPos_auf : WORD = 1000;
EE_Breite : WORD = 32;
EE_Reserve1 : WORD = $FFFF;
EE_ADCPos_min : ARRAY[1..30] OF WORD = ( 0 , 0 , 32 , 64 , 96 , 128 , 160 , 192 ,
224 , 256 , 288 , 320 , 352 , 384 , 416 , 448 ,
480 , 512 , 544 , 576 , 608 , 640 , 672 , 704 ,
736 , 768 , 800 , 832 , 864 , 896 );
EE_Reserve2 : ARRAY[1..2] OF WORD = ( $FFFF , $FFFF );
EE_ADCpos_max : ARRAY[1..30] OF WORD = ( 64 , 96 , 128 , 160 , 192 , 224 , 256 , 288 ,
320 , 352 , 384 , 416 , 448 , 480 , 512 , 544 ,
576 , 608 , 640 , 672 , 704 , 736 , 768 , 800 ,
832 , 864 , 896 , 928 , 960 , 992 );
EE_Midichan : BYTE = 6;
EE_Adroffs : BYTE = 20; // Adroffset (20 als 1. Adresse) bei jumper 100 => Adresse 21
EE_Adr : BYTE = $FF;
ee_Soll : BYTE = $FF;
EE_Data : array[1..8] of word = (0,0,0,0,0,0,0,0);
{$IDATA}
VAR
//Port Definitionen
I_zu[@Pind , 3] : BIT;
I_auf[@Pind , 2] : BIT;
I_Taster[@Pind , 4] : BIT;
O_rot[@PORTB , 4] : BIT;
O_gruen[@PORTB , 5] : BIT;
O_led[@PORTB , 5] : BIT;
O_motor_on[@PORTB , 3] : BIT;
VAR
Midichan : BYTE;
Adroffs : BYTE;
Bloc : BYTE;
Accval , Decval : WORD;
Accpoint , Decpoint : WORD;
Accdelay , Decdelay : WORD;
Teachstep ,
Speedmax ,
Speed_teach ,
Speed_high ,
Speed_low ,
Speed_max : WORD;
//Array 1..30 Schwelerpositionen MIN und MAX
//Namenskonvention:
//ADC => es sind die ADCwerte gemeint also von 0 ..1023 (10 bit)
//SW => es ist die Schwelltrittepos gemeint also von 1 .. 30
Adcpos_min : ARRAY[1..30] OF WORD;
Adcpos_max : ARRAY[1..30] OF WORD;
Adcpos_auf ,
Adcpos_zu : WORD;
Adcpos ,
Adcpos_old ,
Adcpos_soll_min ,
Adcpos_soll_max ,
Adcpos_diff : WORD;
R_heat , L_heat : WORD;
Adc_gleich : BYTE;
Speed : WORD;
Swpos_soll : BYTE;
Highspeed_ab ,
Maxspeed_ab : WORD;
Ready ,
Highspeed ,
Maxspeed ,
Newsoll ,
Ganz_zu ,
Ganz_auf : BOOLEAN;
Ww : WORD;
Operation : BYTE;
Modus : BYTE;
Boardadr ,
Ccadr : BYTE;
Rxinput : BYTE;
M_stat : BYTE;
Rxdat : BYTE;
Count : WORD;
bc : byte; //Byte count
//=== functions =====================================================================================
PROCEDURE Compute_array( speichern : BOOLEAN );
VAR
Diff , Breite , p : WORD; bloc : byte;
BEGIN
EE_ADCPos_zu := Adcpos_zu;
EE_ADCPos_auf := Adcpos_auf;
Diff := Adcpos_auf - Adcpos_zu;
Breite := Diff DIV 30;
EE_Breite := Breite;
p := Adcpos_zu;
IF Adcpos_zu < Breite THEN
Adcpos_min[1] := 0;
ELSE
Adcpos_min[1] := Adcpos_zu - Breite;
ENDIF;
FOR Bloc := 1 TO 30 DO
IF Bloc > 1 THEN
Adcpos_min[Bloc] := p - Breite;
ENDIF;
p := p + Breite;
Adcpos_max[Bloc] := p + Breite;
IF speichern THEN
EE_ADCPos_min[Bloc] := Adcpos_min[Bloc];
EE_ADCpos_max[Bloc] := Adcpos_max[Bloc];
ENDIF;
ENDFOR;
END;
PROCEDURE InitVars;
BEGIN
Accpoint := EE_accpoint;
Accval := EE_ACC;
Decpoint := EE_Decpoint;
Decval := EE_dec;
Accdelay := EE_Accdelay;
Decdelay := EE_Decdelay;
Speed_max := EE_SpeedMax;
Speed_high := EE_SpeedHigh;
Speed_low := EE_SpeedLow;
Speed_teach := EE_SpeedTeach;
Midichan := EE_Midichan;
Adroffs := EE_Adroffs;
Maxspeed_ab := EE_Maxspeed_ab;
Highspeed_ab := EE_Highspeed_ab;
Adcpos_zu := EE_ADCPos_zu;
Adcpos_auf := EE_ADCPos_auf;
Compute_array( TRUE );
Count := 0;
Adcpos_soll_min := 0;
Adcpos_soll_max := 0;
Adcpos := 0;
Adcpos_old := 0;
Swpos_soll := 0;
R_heat := 0;
L_heat := 0;
Boardadr := 0;
IF BIT( Pind , 5 ) THEN
Incl( Boardadr , 0 );
ENDIF;
IF BIT( Pind , 6 ) THEN
Incl( Boardadr , 1 );
ENDIF;
IF BIT( Pind , 7 ) THEN
Incl( Boardadr , 2 );
ENDIF;
Ccadr := Adroffs + Boardadr;
EE_Adr := Ccadr;
END; // InitVars
INTERRUPT RXRDY;
BEGIN
Rxdat := SerInp1; // get ascii value from serial port
IF BIT( Rxdat , 7 ) THEN // bit7=1 => cmd erkannt
IF Rxdat = $B6 THEN // CC auf Kanal 6 erkannt
M_stat := M_warteauf_CC;
ENDIF;
ELSE
IF M_stat = M_warteauf_CC THEN // jetzt werden Daten erwartet
IF Rxdat = Ccadr THEN // mit eigener Adresse vergleichen
M_stat := M_warteauf_VV;
ELSE
M_stat := M_warteauf_Cmd;
ENDIF;
ELSIF M_stat = M_warteauf_VV THEN // vv fehlt noch
IF ( Rxdat > 0 ) AND ( Rxdat < 31 ) THEN
Swpos_soll := Rxdat;
Newsoll := TRUE;
// ee_Soll := Swpos_soll; als Debuginfo
ENDIF;
M_stat := M_warteauf_Cmd;
ENDIF;
ENDIF;
END; // RXRDY
PROCEDURE kurz_rot;
BEGIN
Incl( O_rot );
mdelay( 50 );
Excl( O_rot );
END;
PROCEDURE kurz_gruen;
BEGIN
Incl( O_gruen );
mdelay( 50 );
Excl( O_gruen );
END;
PROCEDURE InitPorts;
BEGIN
DDRB := %11111111;
PWMport1A := 0;
PWMport1B := 0;
END; // InitPorts;
//==== Hauptprogramm ========================================================================================
BEGIN
InitPorts;
InitVars;
EnableInts;
//Start sequenz ausgeben
Incl( O_gruen );
mdelay( 500 );
Incl( O_rot );
mdelay( 500 );
Excl( O_gruen );
mdelay( 500 );
Excl( O_rot );
mdelay( 500 );
Incl( O_gruen );
mdelay( 500 );
Incl( O_rot );
mdelay( 500 );
Excl( O_gruen );
mdelay( 500 );
Excl( O_rot );
mdelay( 500 );
Speed := Speed_high;
Operation := Steht;
Modus := Inaktiv;
Adc_gleich := 0;
Ganz_auf := FALSE;
Ganz_zu := FALSE;
Newsoll := FALSE;
M_stat := M_warteauf_Cmd;
for bc := 1 to 8 do
mdelay(100);
ww := getadc(bc);
ee_data[bc] := ww;
endfor;
LOOP
mdelay( 5 ); // ca 50 µs
//== ADC Routinen ====================================
Adcpos_old := Adcpos;
Adcpos := Getadc( 3 );
IF Adcpos = Adcpos_old THEN
Inc( Adc_gleich );
ELSE
Adc_gleich := 0;
ENDIF;
IF Modus = Inaktiv THEN
Ww := Getadc( 5 );
Ww := Ww SHR 2;
R_heat := Ww;
Ww := Getadc( 6 );
Ww := Ww SHR 2;
L_heat := Ww;
ENDIF;
IF R_heat > 120 THEN
//'Überstrom
ENDIF;
IF L_heat > 120 THEN
//Überstrom
ENDIF;
IF BIT( I_Taster ) THEN// KalibrierTaster betatigt
IF Modus = Inaktiv THEN
Incl( O_rot );
mdelay( 200 );
Excl( O_rot );
mdelay( 200 );
Incl( O_rot );
mdelay( 200 );
Excl( O_rot );
Modus := Teach;
Teachstep := 1;
{Teachmodus:
Step 1 oeffne bis I_AUF aktiv
Step 2 stehen bleiben
Step 3 Schliessen bis I_zu aktiv
step 4 stehen bleiben
step 5 Positon als Pos_zu speichern
Step 6 oeffne bis I_AUF aktiv
Step 7 stehen bleiben
Step 8 Positon als Pos_auf speichern
Fertig ===========================================}
ENDIF;
ENDIF;
IF Modus = Teach THEN
Incl( O_rot );
Speed := Speed_teach;
CASE Teachstep OF
8 :
mdelay( 500 );
Adcpos := Getadc( 3 );
EE_ADCPos_auf := Adcpos;
Adcpos_auf := Adcpos;
Excl( O_rot );
Modus := Inaktiv;
Compute_array( TRUE );
|
7 :
IF BIT( I_auf ) THEN
IF Operation = Steht THEN
Teachstep := 8;
ENDIF;
ENDIF;
|
6 :
IF Operation = Steht THEN
Operation := Oeffnen;
Teachstep := 7;
ENDIF;
|
5 :
mdelay( 500 );
Adcpos := Getadc( 3 );
EE_ADCPos_zu := Adcpos;
Adcpos_zu := Adcpos;
Teachstep := 6;
|
4 :
IF BIT( I_zu ) THEN
IF Operation = Steht THEN
Teachstep := 5;
ENDIF;
ENDIF;
|
3 :
IF Operation = Steht THEN
Operation := Schliessen;
Teachstep := 4;
ENDIF;
|
2 :
IF BIT( I_auf ) THEN
IF Operation = Steht THEN
Teachstep := 3;
mdelay( 500 ); //warten zur beruhigung
ENDIF;
ENDIF;
|
1 :
Operation := Oeffnen;
Teachstep := 2;
|
ENDCASE;
ENDIF;
IF Newsoll THEN
Incl( O_rot );
Incl( O_gruen );
mdelay( 200 );
Excl( O_rot );
Excl( O_gruen );
Adcpos_soll_min := Adcpos_min[Swpos_soll];
Adcpos_soll_max := Adcpos_max[Swpos_soll];
Ganz_auf := ( Swpos_soll = 30 );
Ganz_zu := ( Swpos_soll = 1 );
IF Adcpos > Adcpos_soll_max THEN
Adcpos_diff := Adcpos - Adcpos_soll_max;
ELSIF Adcpos < Adcpos_soll_min THEN
Adcpos_diff := Adcpos_soll_min - Adcpos;
ELSE
Adcpos_diff := 0;
ENDIF;
Newsoll := FALSE;
Highspeed := FALSE;
Maxspeed := FALSE;
IF Adcpos_diff > 0 THEN
IF Adcpos_diff > Maxspeed_ab THEN
Maxspeed := TRUE;
ELSIF Adcpos_diff > Highspeed_ab THEN
Highspeed := TRUE;
ENDIF;
ENDIF;
IF Modus = Inaktiv THEN
Modus := Work;
ENDIF;
ENDIF;
IF Modus = Work THEN
IF ( Adcpos < Adcpos_soll_min ) OR Ganz_auf THEN
Operation := Oeffnen;
ENDIF;
IF ( Adcpos > Adcpos_soll_max ) OR Ganz_zu THEN
Operation := Schliessen;
ENDIF;
IF ( Adcpos >= Adcpos_soll_min ) AND
( Adcpos <= Adcpos_soll_max ) AND
( Operation > Stoppen ) THEN
IF ( Operation = Schliessen ) AND NOT ( Ganz_zu ) THEN
Operation := Stoppen;
//kurz_rot;
ENDIF;
IF ( Operation = Oeffnen ) AND NOT ( Ganz_auf ) THEN
Operation := Stoppen;
//kurz_rot;
ENDIF;
ENDIF;
ENDIF;
IF Operation = Oeffnen THEN
Incl( O_motor_on );
kurz_gruen;
mdelay( 200 );
//Set O_rot
PWMport1A := 0;
IF Modus = Teach THEN
PWMport1B := Speed_teach;
ELSE
IF Maxspeed THEN
IF PWMport1B < Accpoint THEN
PWMport1B := PWMport1B + Accval;
mdelay( Accdelay );
ELSE
PWMport1B := Speed_max;
ENDIF;
ELSE
IF Highspeed THEN
PWMport1B := Speed_high;
ELSE
PWMport1B := Speed_low;
ENDIF;
ENDIF;
ENDIF;
IF BIT( I_auf ) THEN
Operation := Stoppen;
Ganz_auf := FALSE;
ENDIF;
ENDIF; // Öffnen ==================================================
IF Operation = Schliessen THEN
Incl( O_motor_on );
kurz_gruen;
mdelay( 200 );
//excl(O_rot);
PWMport1B := 0;
IF Modus = Teach THEN
PWMport1A := Speed_teach;
ELSE
PWMport1A := Speed_low;
IF Maxspeed THEN
IF PWMport1A < Accpoint THEN
PWMport1A := PWMport1A + Accval;
mdelay( Accdelay );
ELSE
PWMport1A := Speed_max;
ENDIF;
ELSE
IF Highspeed THEN
PWMport1A := Speed_high;
ELSE
PWMport1A := Speed_low;
ENDIF;
ENDIF;
ENDIF;
IF BIT( I_zu ) THEN
Operation := Stoppen;
Ganz_zu := FALSE;
ENDIF;
ENDIF; // Schliessen ==============================================
IF Operation = Stoppen THEN
kurz_rot;
IF Maxspeed THEN
IF PWMport1B > Decval THEN
IF PWMport1B > Decpoint THEN
PWMport1B := PWMport1B - Decval;
mdelay( Decdelay );
ELSE
PWMport1B := 0;
ENDIF;
PWMport1B := 0;
ENDIF;
IF PWMport1A > Decval THEN
IF PWMport1A > Decpoint THEN
PWMport1A := PWMport1A - Decval;
mdelay( Decdelay );
ELSE
PWMport1A := 0;
ENDIF;
PWMport1A := 0;
ENDIF;
ELSE
PWMport1A := 0;
PWMport1B := 0;
ENDIF;
IF Adc_gleich > 10 THEN
Operation := Steht;
Ganz_auf := FALSE;
Ganz_zu := FALSE;
IF Modus = Work THEN
Modus := Inaktiv;
Excl( O_rot );
//Reset O_motor_on
//Reset O_rot
ENDIF;
ENDIF;
ENDIF; // Stoppen =======================================================
Inc( Count );
IF Count = 10000 THEN
//Toggle( O_led );
Count := 0;
ENDIF;
ENDLOOP;
END Jalousie_v1.