Go Down

Topic: Ch-6: Interrupt Structure of ATmega328 (Read 11527 times) previous topic - next topic

GolamMostafa

Jun 06, 2017, 07:44 pm Last Edit: Aug 22, 2017, 07:07 am by GolamMostafa
6.1 Meaning of Interrupting the ATmega328 Microcontroller

(1) Interrupting the ATmega328 Microcontroller (MCU) means:

(a) Telling the MCU to suspend (not stop) what it has been doing (the main line program, MLP). The MCU has been continuously blinking the LED (L) of the Arduino Learning Kit (Fig-6.1) --- this could be an example of an MLP.



Figure-6.1: Diagram to explain the meaning of interrupting the MCU

The command by which we tell the MCU to suspend the MLP is given in the form of voltage logic, and it is applied on Pin-4 of the MCU. This command signal is known as Interrupting Signal or Interrupt Request Signal (IRQ). In Fig-6.1, the IRQ-signal is applied using a switch (K1); it is called Interrupting Device.  The trigger level of the IRQ-signal is Active Low. It could be Rising Edge, Active High, or Falling Edge of a pulse. The internal pull-up resistor (Rp) keeps Pin-4 at LH-state. As the user presses down and releases K1, a momentary LL-signal appears at Pin-4. The MCU detects this change and immediately gets interrupted. The interrupt associated with Pin-4 has a symbolic name called INT0 (interrupt type 0). PD2 is the port-line that has been used to work as interrupt line. The direction of PD2-line must be input with internal pull-up enabled.

The ATmega328 has another physical pin (Pin-5) which can also receive IRQ-signal from external source. The interrupt associated with Pin-5 is INT1 (interrupt type 1). As the IRQ-signal is coming from external hardware device, we call it Hardware Interrupt Signal (HWI).

(b) The MCU goes to the side job (the interrupt sub routine, ISR). Let us designate this side job with the symbolic name ISRINT0 (ISR due to INT0 interrupt). For example: The MCU blinks LED2 (connected at PB0-line) only for 5 times.

(c) The MCU will finish the ISRINT0, and then it will resume the MLP.

(2) The interrupt process of Step-1 can be described by the following diagram (Fig-6.2) which is known as Interrupt Process Diagram (IPD).



Figure-6.2: Interrupt Process Diagram for INT0

(a) Assume that the MLP has been uploaded into Code Memory (Flash) starting at location 0040h. The symbolic name of this location is ML1 (Label 1 of MLP). The ISRINT0 has also been uploaded into flash starting at an arbitrary location of kkkkh. The MLP has begun execution at time, t0.

The Atmega328 can also be interrupted from outside by toggling the logic level of one or more of its physical pin. This is known as Pin-change Interrupt.

(b) At time t1, the MLP has arrived at label ML2 and during the execution of the instruction of this label, the MCU has received IRQ-signal at its INT0-pin. If IRQ-signal would not be present, the MCU would continue its MLP by executing the next instruction at label ML3. The label ML3 is known as Return Address from which the MCU will resume MLP after returning from ISRINT0.

(c) As the IRQ-signal has arrived, the MCU will finish the current instruction of label ML2; it will save the return address (the numerical value yyyyh of ML3) onto a special block of internal SRAM known as Stack Memory or simply Stack.

(d) The MCU will jump to the beginning address (kkkkh with label ISL1) of ISRINT0 and will begin the execution of the ISR at time t2. Just after the arrival at the ISRINT0, the user may save some important data onto Stack by executing push instruction.

(e) At time t3, the MCU will finish the execution of the ISRINT0; it is now ready to return to the MLP. The MCU will first retrieve the important data from Stack by executing pop instruction and then the MCU will execute reti (return from interrupt) instruction to retrieve return address (yyyyh of ML3) from the Stack.

(f) MCU will resume the execution of MLP at label ML3 and it will happen at time t4.

(g) At label ML4, the MCU will jump back to label ML1 in order to continue the blinking process of LED (L).  

GolamMostafa

#1
Jun 06, 2017, 09:59 pm Last Edit: Jun 08, 2017, 07:53 pm by GolamMostafa
6.2  The Interrupt Vector and its relation with the Beginning Address of the ISR

(1)  In Section-6.1, we have seen that the interrupt process is involved with two jobs: MLP and ISR. The MCU keeps executing the MLP (blinking L). When there occurs an interrupt, the MCU is forced to suspend the MLP, and then it jumps to the ISR. Now, the question: how does the MCU know the beginning address of the ISR, which the user has arbitrarily assigned? In this Section, we will explore this issue and other concepts of interrupt.

(2)  The Memory Map of Fig-6.3 shows the storage scenario of MLP and ISR. The boundary addresses for various blocks of memory spaces are arbitrarily chosen except for Interrupt Vector Space and Boot Loader Space which are almost fixed.


Figure-6.3: Memory Map showing the storage of MLP and ISR

(3)  In Assembly language Programming, we can fix the beginning address of MLP and ISRINT0 at desired locations using the directives .org 0x0040 and .org 0x3700. In HL Programming, similar things are done; but, beyond the knowledge of the programmer. To understand the role of Interrupt vector for helping the MCU to reach at the beginning address of ISRINT0, we will attention on the addresses shown in Fig-6.3.

(4)  In the MLP, the MCU is busy in blinking the LED (L); the IRQ-signal may arrive at any time. This is known as asynchronous arrival of the IRQ-signal. There is absolutely no timing relationship between the stepping of the MLP instructions and the activation of the external interrupting device (K1 in Fig-6.1).

(5)  Upon arrival of the IRQ-signal, as we will see in later sections, the MCU does suspend the MLP and goes to the ISRINT0 to blink LEDR2. The question: how does the MCU know the value (3700h) of the beginning address of ISRINT0, which the user has keyed at his own choice?

(6)  The answer to the question of Step-5 is here. The architecture of the ATmega328 dictates that the MCU will make an automatic jump to the location 0002h whenever an IRQ-signal (assuming that the interrupt gates are closed!, Fig-6.4) arrives at its INT0-pin. The MCU is transferring program control to a known location; this can be compared with the concept of a traditional vector (a directed line with an arrow head). The number 0002h is termed vas Interrupt Vector. It is an interrupt vector as it has appeared due to the presence of an interrupt signal. In ATmega328, there is an interrupt vector for every interrupt. The ATmega328 supports as many as 26 interrupts. The memory block known as Interrupt Vector Space (Fig-6.3) of the flash has been kept aside to accommodate the interrupt vectors of all these 26 interrupts.

(7)  Now, the user (the programmer) knows the location 0002h; he also knows the value of the beginning address of his ISRINT0, which is 3700h. During initialization, the user can comfortably establish the link between these two locations by inserting the 'jmp 0x3700' instruction at location 0x0002.    

GolamMostafa

#2
Jun 07, 2017, 03:16 am Last Edit: Jun 07, 2017, 08:32 pm by GolamMostafa
6.3 Internal Structure of INT0 Interrupt Logic

ATmega328 can be made to appear as a smart machine when it is efficiently trained thorough programming. It has many features which can be conditioned to provide various functions according to the needs of the users. Among all these features, the ability of the MCU to make quick response to external and internal interrupts is seen as its most sophisticated faculty. The HLL Programming Language hides to the users (programmers) many of the internal hardware details of the MCU. As a result, the programmer faces extreme difficulties to correct a malfunctioning program in a situation where multiple peripheral devices are engaged in data exchange through nested interrupts.  In this section, we will explore the internal hardware details of INT0-interrupt (Fig-6.4) in order to formulate methodology for smooth development/debug of program for an interrupt process.    

(1) Conceptual View of the internal hardware details of INT0-interrupt is depicted in Fig-6.4.


Figure-6.4: Internal structure of INT0 interrupt of ATmega328

(2) In Fig-6.4, we have interfaced the interrupting device (K1) through a one-shot IC of type 74LS123. This is to avoid multiple generation of IRQ-signal which the switch K1 will create once it is pressed down. A mechanical key like K1 makes hundreds of to-and-fro movements (bouncing) before it settles to its final open/close position. The insertion of U1X (74LS123) ensures that the INT0-pin will always receive only one clean, sharp, and short-duration (about 100 µs) interrupt pulse.  

(3) The IRQ-signal from Pin-5 of U1X enters at DPin-2 (Digital Pin 2) of the Arduino. The DPin-2 is solidly connected with Pin-4 (INT0/PD2-pin) of the ATmega328 via PCB track.

(4) The interrupt logic can be programmed to detect any one of the following four characteristics of the incoming IRQ-signal: Low level, Rising Edge, High Level, and Falling Edge. The programming is done by putting appropriate data (described in the data sheet) into the EICRA (External Interrupt Control Register A) of the MCU.

(5) To detect Low Level or falling Edge of the IRQ-signal, the internal or external pull-up resistor must be connected. The internal pull-up is enabled with the help of MCUCR- , DDRD-, and PORTD-registers of the MCU.

(6) To detect High Level or Rising Edge of the IRQ-signal, the internal or external pull-up resistor must remain disconnected; instead, an external pull-down resistor (about 5k) must be connected with the INT0-pin.

(7) Whenever an IRQ-signal arrives at the INT0-pin, it is always detected by the interrupt logic circuit and its presence is recorded by putting LH in the INTF0 (Interrupt-0 Flag) bit of the EIFR-register (External Interrupt Flag Register) under the following conditions:

(a) If the trigger level of the IRQ-signal is Low or High, then the INTF0-bit will remain at LH-state as long as the IRQ-signal remains active. This means that the active level of the IRQ-signal is not latched.

(b) If the trigger level of the IRQ-signal is Falling Edge or Rising Edge, then the INTF0-bit will remain at LH-state even at the absence of IRQ-signal. This means that the active level of the IRQ-signal is latched.

(8) The MCU on behalf of the user can deliver services to the interrupter by looking at the INTF0-bit. This is known as Polled Interrupt. In this case, the user has to clear the INTF0-bit manually (using instruction) by putting LH back into this bit.

(9) The MCU can also deliver services to the interrupter being interrupted by the INTF0-bit. This will happen (MCU will be interrupted) if the INT0- and I-switches are kept in closed conditions during initialization. Upon interruption, the MCU automatically jumps to location 0x0002 (the vector location) from which it is again directed to jump at the beginning of ISRINT0 subroutine (Interrupt Sub Routine due to INT0 interrupt). This process of delivering services through interrupt is known as Vector Interrupt. During vectored interrupt, the INTF0-bit is automatically cleared when the MCU arrives at the ISRINT0.

(10) The INT0-switch corresponds to a bit-0 of the EIMSK (External Interrupt mask Register) register. This bit controls the automatic vectoring of the INT0-interrupt only. This bit is known as local interrupt enable/disable switch/gate.

(11) The I-switch corresponds to bit-7 of the SREG (Status Register) register of the MCU. It controls auto vectoring of all the 26 interrupts of the ATmega328. This bit is known as global interrupt switch/gate.    

(12) Upon entering into the ISRINT0, the MCU disables all interrupts by putting LL at the I-bit of the SREG-register. The local interrupt bit remains unaffected.

(13) After finishing the ISRINT0 and before making a return to MLP, the MCU enabled the global interrupt by putting LH at the I-bit of the SREG-register. The MCU is again ready to respond to interrupts.

(14) Registers involved in the Operation of INT0-interrupt
(a) EICRA : External Interrupt Control register A : It selects trigger level of IRQ-signal.
(b) EIFR   : External Interrupt Flag Register        : It records the status of the arrival of IRQ-signal
(c) EIMSK : External Interrupt Mask Register      : It controls the open/close condition of INT0-switch.
(d) SREG  : Status Register                             : It control the open/close condition of I-switch.
(e) MCUCR: MCU Control Register                    : MCCR, DDRD, and PORTD Registers, together,
DDRD  : Data Direction Register for PORTD     controls the open/close condition of the internal
PORTD : Port-D Register                               pull-up resistor

(15) Although the above statements are specifically made referring to INT0 interrupt for clarity and brevity, they are equally and generally applicable for all kinds of polled/vectored interrupts of ATmega328 Microcontroller.

GolamMostafa

#3
Jun 07, 2017, 09:49 pm Last Edit: Jun 08, 2017, 02:47 pm by GolamMostafa
6.4  Development of Program for Functional Check of INT0-interrupt

Refer to Fig-6.5 shown below; MLP program is designed to blink LED (L) continuously. The ISRINT0 program will blink LED2 only for 5 times. The K1 is the interrupting device. The LCD panel is added to monitor MCU-registers' values at different phases of the executing interrupt process.


Figure-6.5: Arduino UNO based set up for functional check of INTO interrupt

(1) Text/Pseudo/Mixed Codes
Code: [Select]

Void setup()
{
    L11: Establish link between Interrupt Vector Address (0x0002) of INT0
           with its corresponding interrupt sub routine (ISRINT0)
    IRQ  INT0  INTF0  0x0002  ISRINT0
          
         .org   0x0002
          rjmp ISRINT0
            
(a) The codes of the ISRINT0 routine come after the codes of setup() and loop() functions.
The assembler can always compute the numerical value for the offset of ISR subroutine.
During final phase of assembly, the symbolic name ISRINT0 is replaced by the numerical
value of this offset. Upon interruption, the MCU finds the interrupt sub routine at a
distance given by the operand of the [i]rjmp[/i]instruction.

(b) In HL Programming, the above task of L11 is carried out by declaring the ISRINT0 as a function with a pre-defined name (ISR) and argument (INT0_vect): ISR(INT0_vect). During compilation time, the compiler understands that the stated subroutine (ISR) will be called upon when there is an interrupt on the INT0-pin whose interrupt vector is 0x0002.

(c) In HL Programming, the task L11 can also be carried out by declaring another kind of function whose three arguments are passed as symbolic names. These symbolic names have pre-defined meanings; the meanings are transformed into executable binary numbers during compilation time.

The function: attachInterrupt (arg1, arg2, arg3);

(i) arg1 is a function: [i]digitalPinToInterrupt(2)[/i]. The function says that the 'Digital Pin 2' of Arduino, which is solidly connected with INT0(PD2/Pin-4)-line of the ATmega328 will work as interrupt line for Interrupt Type 0. And accordingly, the PD2-line will work as input-line with internal pull-up resistor connected.

(ii) arg2 : ISRINT0. It is a name (any valid identifier is acceptable) which the user must use as a name for the function of his interrupt sub routine like ISRINT0(). There is no argument for this function. The 'INT0' can be deleted; however, it is given for easy remembering that this ISR is due to INT0 interrupt. The arg2 links itself to the correct inetrrupt vector (0x0002) from the 'digitalPin' of the previous argument.

(iii) arg3 : Trigger level of IRQ-signal (AL< RE, AH, FE, CH). The compiler knows the meanings of these symbolic names and assigned appropriate values into the registers of the MCU.  

//-----------------------------------------------------------------------------------------------------
L12: Initialize LCD as needed (LCD type and Cursor Position)
//----------------------------------------------------------------------------------
L13: Configure PD2-line (with internal pull-up) to work as interrupt line for INT0 interrupt
L14: Select trigger level of IRQ-signal (Falling Edge)
L15: Close local INT0-switch for auto vectoring to ISRINT0
L16: Close global I-switch for auto vectoring to ISRINT0
//--------------------------------------------------------------------------------------
L17: Set direction of PB5-line as output to drive L of MLP
L18: Set direction of PD4-line as output to drive LED2 of ISR(INT0_vect)
//----------------------------------------------------------------------------------------------

}

Void loop()
{
     L21: ON LED (L)
     L22: Insert 1-sec Time Delay
     L23: OFF LED (L)
     L24: Insert 1-sec Time Delay
}

ISRI(INT0_vect)
{
    L31: Enable global interrupt via I-switch // with this delay() function will not work here
    
    L32: ON LED2
    L33: Insert 1-sec Time Delay
    L34: OFF LED2
    L35: Insert 1-sec Time Delay
    L36: Repeat Step-L32 to L35 for 4 times more.
    
    L37: Return to Main Line Program (MLP)
}


          
P642 (2) Arduino Coding-A for the program codes of Step-1
Code: [Select]

#include <LiquidCrystal.h>
//LiquidCrystal lcd(RS, E, D4, D5, D6, D7); //declaration of LCD wiring function
LiquidCrystal lcd (5, A0, A1, A2, A3, A4); //definition of LCD wiring function

Void setup()
{
   //Task of L11 is done by declaring ISR(INT0_vect) function at the end of loop() function

   lcd.begin(16, 2); //L12: 16x2 LCD ; 2-line; each line has
   lcd.setCursor(1, 0); //L12: DP1 postion of TopLine

    //----- the following six lines connects internal pull-up with PD2-line------------------
    DDRD = B11111011; //L13:  PD2 as input; value has come from data sheet
    bitSet(PORTD, 2); //L13:
    bitClear(MCUCR, 4); //L13
    //---------------------------------------------------
    EICRA = B00000010; //L14: falling edge trigger level for of INT0; value comes from data sheet
    EIMSK = B00000001; //L15: local INT0-switch is closed; value has come from data sheet
    bitSet(SREG, 7); //L16: Global I-switch is closed; alternate code : sei() ; opposite : cli()

    //---------------------------------------------------
    pinMode(13, OUTPUT); //L17:
    pinMode(4, OUTPUT); //L18:

    lcd.print(EIMSK, 16); //check INT0-bit for 1 before the MLP is interrupted
    lcd.setCursor(5, 0); //
    lcd.print)SREG, 16); // check I-bit for 1 before MLP is interrupted

}

Void loop()
{
    digitalWtite(13, HIGH); //L21:
    delay(1000); //L22:
    digitalWrite(13, LOW); //L23:
    delay(1000); //L24
}

ISR(INT0_vect)
{
    lcd.setCursor(1, 1); //cursor at DP1 bottomLine
    lcd.print(EIMSK, 16); //check INT0-bit for 1 after interruption
    lcd.setCursor(5, 1);
    lcd.print(SREG, 16); //check I-bit for 0 after interruption

    interrupts(); //L31: Set I-bit of SREG-register; global I-switch is closed

    for (int n=0; n<=4; n++)
   {
      digitalWrite(4, HIGH); //L32:
      delay(1000); //L33:
      digitalWrite(4, LOW); //L34:
      delay(1000); //L35;
      //--------------------------------------
      reti(); //L37: Return to MLP from ISR
}



(3) Compile and upload P642 of Step-2. Press the interrupting device K1. Check that the interrupt process works as expected. Also, monitor the values of EIMSK- and SREG-registers in the LCD. Decode their contents looking at the data sheet and observe that the I-bit becomes LL after interruption; but, the INT0-bit remains unaffected.

(4) Arduino Instruction Set Summary for Interrupts


P645 (5) Arduino Coding-B for the program codes of Step-1
Code: [Select]

#include <LiquidCrystal.h>
//LiquidCrystal lcd(RS, E, D4, D5, D6, D7); //declaration of LCD wiring function
LiquidCrystal lcd (5, A0, A1, A2, A3, A4); //definition of LCD wiring function

Void setup()
{
    //Task of L11 is done by declaring ISRINT0() function at the end of loop() function

    lcd.begin(16, 2); //L12: 16x2 LCD ; 2-line; each line has
    lcd.setCursor(1, 0); //L12: DP1 postion of TopLine

    //----- the following single function does all tasks of----------------------------
    attachInterrupt(digitalPinToInterrupt(2), ISRINT0, FALLING); //L13-L16

    //---------------------------------------------------
    pinMode(13, OUTPUT); //L17:
    pinMode(4, OUTPUT); //L18:
    lcd.print(EIMSK, 16); //check INT0-bit for 1 before the MLP is interrupted
    lcd.setCursor(5, 0); //
    lcd.print)SREG, 16); // check I-bit for 1 before MLP is interrupted

}

Void loop()

{
    digitalWtite(13, HIGH); //L21:
    delay(1000); //L22:
    digitalWrite(13, LOW); //L23:
    delay(1000); //L24
}

Void ISRINT0()
{
    EIMSK = 0x00;
    lcd.setCursor(1, 1); //cursor at DP1 bottomLine
    lcd.print(EIMSK, 16); //check INT0-bit for 1 after interruption
    lcd.setCursor(5, 1);
    lcd.print(SREG, 16); //check I-bit for 0 after interruption
    //--------------------------------------------------
    interrupts();; //L31: Set I-bit of SREG-register; global I-switch is closed

    lcd.setCursor (9, 1);
    lcd.print(EIMSK, 16);
  
    for (int n=0; n<=4; n++)
    {
        digitalWrite(4, HIGH); //L32:
        delay(1000); //L33:
        digitalWrite(4, LOW); //L34:
        delay(1000); //L35;
    }

    reti(); // must be here for the MCU to return to MLP properly
}



(6) Compile and upload P645 program. Press the interrupting switch K1 and check that the interrupt process works as scheduled.

(7) Insert suitable commands at the chosen points of the program P645 in order to verify the validity of the instructions of Step-4.

urmil123

Quote
Code: [Select]

for (int n=0; n<=4; n++)
   {
       digitalWrite(4, HIGH); //L32:
       delay(1000); //L33:
       digitalWrite(4, LOW); //L34:
       delay(1000); //L35;
   }


We know only one ISR can run at a time and since delay() function requires interrupts to work, will it work under an ISR?
Stalking the closest to the edge
Imposition of depravity
Sanity holding by a thread
Desperation draws them close to me

AWOL

The code doesn't even compile, so I'm not sure why it was posted.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

GolamMostafa

#6
Aug 15, 2017, 02:22 pm Last Edit: Aug 15, 2017, 03:11 pm by GolamMostafa
The code doesn't even compile, so I'm not sure why it was posted.
Sir,

This is Education and Teaching Section. I have to deal with tens of pupils who are individually using Arduino UNO Kits for their course works. The pupils desire that I prepare and post the class lectures in the Education and Teaching Section of the Forum so that they can read it online and down load it.

It may not be possible for all the time to test my all propositions and codes. I admit my all mistakes which are, to the best level of my sincerity, unintentional. However, if my endeavors are appearing as creating more problems for the pupils rather than offering them the benefits they are enjoying now I would certainly refrain myself from exercising these unnecessary efforts.

Thanks,


dannable

The pupils desire that I prepare and post the class lectures in the Education and Teaching Section of the Forum so that they can read it online and down load it.
In that case shouldn't you be hosting it on your own web site?
Beginners guide to using the Seeedstudio SIM900 GPRS/GSM Shield

GolamMostafa

In that case shouldn't you be hosting it on your own web site?
The decision should come from the Moderator.

AWOL

The pupils desire that I prepare and post the class lectures in the Education and Teaching Section of the Forum so that they can read it online and down load it.
And the pupils are happy to correct the code themselves, after downloading it?
Do you pre-warn them that it won't compile, and then won't work, even when the syntactic errors are fixed?
Is this part of the teaching process?

Doesn't your faculty have its own website?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

GolamMostafa

#10
Aug 15, 2017, 03:28 pm Last Edit: Aug 15, 2017, 07:37 pm by GolamMostafa
We know only one ISR can run at a time and since delay() function requires interrupts to work, will it work under an ISR?
Let us see what happens when an IRQ arrives at the INT0-pin and before the ISR is executed:
(1)  The MCU disables the Global Interrupt Enable Bit (I-bit of SREG is made 0)
(2)  The ISR contains a program that blinks a LED for 5 times. This blinking task has used the built-in delay() function of the Arduino.
(3)  The delay() function works on interrupts; but the interrupt is disabled. So, we have to re-enable it just after arriving at the ISR, and it is done by executing the instruction interrupts();.
(4)  Please down load and open the program P645.ino, and you see that the instruction interrupts(); has already been executed just after arriving at the ISR.
(5)  Therefore, the ISR should work normally. The inclusion of reti(); helped in my case for the MCU to make a normal return to the MLP though it should not be required.

BTW: To the best of my knowledge, I compiled and tested the program P645.ino before posting it. I have attached the original file and also has typed it in the code box. It is a good practice that we use the attached file rather than the typed file which might have typographical errors.

Have you compiled the program? Have you seen any errors?  

GolamMostafa

Quote
Doesn't your faculty have its own website?
Rather than cross questioning and answering, please pass the verdict according to the rules of the Forum. Enough is enough!

AWOL

Code: [Select]
Void setup()
{
I don't need to present that to the compiler to know that it will be spat out.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

AWOL

#13
Aug 15, 2017, 03:49 pm Last Edit: Aug 15, 2017, 03:51 pm by AWOL
Rather than cross questioning and answering, please pass the verdict according to the rules of the Forum. Enough is enough!

I don't want you to waste your time and effort, but also I don't want anyone posting authoritative-looking topics that are misleading.

I don't have the time to check all posts on the forum, nor do the other mods, but ones with blatant (to me) mistakes, or topics reported to the moderators will obviously be pointed out.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

GolamMostafa

And the pupils are happy to correct the code themselves, after downloading it?
Ans:  Ask the pupils.

Do you pre-warn them that it won't compile, and then won't work, even when the syntactic errors are fixed?
Ans:  The question should come from the pupils/Evaluation Committee.

Is this part of the teaching process?
Ans: The question again should come from the Evaluation Committe.

Doesn't your faculty have its own website?
Ans: No need! The faculty and the pupils have paid hundreds of dollars for the Arduino Learning Kits. It is their rights and not the privileges to enjoy all the available resources of the Forum subject to the compliance of the rules of the Forum.

Go Up