diff --git a/freertos_exercise_1.ino b/freertos_exercise_1.ino
new file mode 100644
index 0000000000000000000000000000000000000000..1294d78268bcf413f981ab33aa9e6c5d586a2e80
--- /dev/null
+++ b/freertos_exercise_1.ino
@@ -0,0 +1,50 @@
+#include <FreeRTOS.h>
+#include <task.h>
+ 
+#define SERIAL_PORT Serial
+#define BLINK_ON_TIME   2000
+#define BLINK_OFF_TIME  2000
+
+/* Dimensions of the buffer that the task being created will use as its stack.
+  NOTE:  This is the number of words the stack will hold, not the number of
+  bytes.  For example, if each stack item is 32-bits, and this is set to 100,
+  then 400 bytes (100 * 32-bits) will be allocated. */
+#define STACK_SIZE 200
+
+/* Structure that will hold the Task Control Block of the task being created. */
+StaticTask_t xTaskBuffer;
+ 
+/* Buffer that the task being created will use as its stack.  Note this is
+  an array of StackType_t variables.   . */
+StackType_t xStack[ STACK_SIZE ];
+ 
+ 
+void setup() 
+{
+  
+  SERIAL_PORT.begin(115200);
+  pinMode(LED_BUILTIN, OUTPUT);
+  xTaskCreateStatic(led, "led", STACK_SIZE, NULL, configMAX_PRIORITIES - 1, xStack, &xTaskBuffer);
+}
+
+void led(void *pvParameters)
+{
+  (void) pvParameters;
+  while (1)
+  {
+     SERIAL_PORT.println("LED ON!");
+    digitalWrite(LED_BUILTIN, HIGH);
+    vTaskDelay(BLINK_ON_TIME);
+
+
+    SERIAL_PORT.println("LED OFF!");
+    digitalWrite(LED_BUILTIN, LOW);
+    vTaskDelay(BLINK_OFF_TIME);
+   }
+}
+
+ 
+
+void loop() {
+ 
+}
diff --git a/freertos_exercise_2_base.ino b/freertos_exercise_2_base.ino
new file mode 100644
index 0000000000000000000000000000000000000000..aca119fae086215631edc0c03dec1e9fbfde9600
--- /dev/null
+++ b/freertos_exercise_2_base.ino
@@ -0,0 +1,53 @@
+#include <FreeRTOS.h>
+#include <task.h>
+ 
+#define SERIAL_PORT Serial
+#define BLINK_ON_TIME   2000
+#define BLINK_OFF_TIME  2000
+
+/* Dimensions of the buffer that the task being created will use as its stack.*/
+#define STACK_SIZE 200
+
+/* Structure that will hold the Task control block of the tasks being created. */
+StaticTask_t xTaskBuffer_A;
+StaticTask_t xTaskBuffer_B;
+
+/* Buffer that the task being created will use as its stack.   */
+StackType_t xStack_A[ STACK_SIZE ];
+StackType_t xStack_B[ STACK_SIZE ];
+
+ 
+void setup() 
+{
+  
+  SERIAL_PORT.begin(115200);
+  pinMode(LED_BUILTIN, OUTPUT);
+
+  xTaskCreateStatic(led_ON, "led_ON", STACK_SIZE, NULL, 1, xStack_A, &xTaskBuffer_A);
+  xTaskCreateStatic(led_OFF, "led_OFF", STACK_SIZE, NULL, 1, xStack_B, &xTaskBuffer_B);
+}
+
+void led_ON(void *pvParameters)
+{
+  (void) pvParameters;
+  while (1)
+  {
+     SERIAL_PORT.println("LED ON!");
+    digitalWrite(LED_BUILTIN, HIGH);
+    vTaskDelay(BLINK_ON_TIME);
+   }
+}
+
+void led_OFF(void *pvParameters)
+{
+  (void) pvParameters;
+  while (1)
+  {
+     SERIAL_PORT.println("LED OFF!");
+    digitalWrite(LED_BUILTIN, LOW);
+    vTaskDelay(BLINK_OFF_TIME);
+   }
+}
+
+void loop() { 
+}
diff --git a/freertos_exercise_3_base.ino b/freertos_exercise_3_base.ino
new file mode 100644
index 0000000000000000000000000000000000000000..7a3d699c26a5dfc261f4b7de36169ff31018e1c8
--- /dev/null
+++ b/freertos_exercise_3_base.ino
@@ -0,0 +1,140 @@
+#include <FreeRTOS.h>
+#include <task.h>
+#include <semphr.h>
+#include <FreeRTOSConfig.h>
+
+#define SERIAL_PORT Serial
+
+/* Declare a variable of type QueueHandle_t. This is used to store the handle
+to the queue that is accessed by all three tasks. */
+QueueHandle_t xQueue;
+
+void vPrintString( const char *pcString )
+{
+ /* Write the string to stdout, using a critical section as a crude method of
+ mutual exclusion. */
+ taskENTER_CRITICAL();
+ {
+  SERIAL_PORT.println(pcString );
+   fflush( stdout );
+ }
+ taskEXIT_CRITICAL();
+}
+
+
+static void vSenderTask( void *pvParameters )
+{
+  int32_t lValueToSend;
+  BaseType_t xStatus;
+  TickType_t  xLastWakeTime = xTaskGetTickCount();
+
+  /* Two instances of this task are created so the value that is sent to the
+ queue is passed in via the task parameter - this way each instance can use
+ a different value. The queue was created to hold values of type int32_t,
+ so cast the parameter to the required type. */
+ lValueToSend = ( int32_t ) pvParameters;
+ /* As per most tasks, this task is implemented within an infinite loop. */
+ for( ;; )
+ {
+   /* Send the value to the queue.
+   The first parameter is the queue to which data is being sent. The
+   queue was created before the scheduler was started, so before this task
+   started to execute.
+   The second parameter is the address of the data to be sent, in this case
+   the address of lValueToSend.
+   The third parameter is the Block time – the time the task should be kept
+   in the Blocked state to wait for space to become available on the queue
+   should the queue already be full. In this case a block time is not
+   specified because the queue should never contain more than one item, and
+   therefore never be full. */
+   xStatus = xQueueSendToBack( xQueue, &lValueToSend, pdMS_TO_TICKS( 1000 ) );
+   if( xStatus != pdPASS )
+   {
+       /* The send operation could not complete because the queue was full -
+       this must be an error as the queue should never contain more than
+       one item! */
+      vPrintString( "Could not send to the queue.\r\n" );
+   }
+    
+   vTaskDelayUntil( &xLastWakeTime, pdMS_TO_TICKS( 1000 ) );   
+
+ 
+ }
+}
+
+
+static void vReceiverTask( void *pvParameters )
+{
+  /* Declare the variable that will hold the values received from the queue. */
+  int32_t lReceivedValue;
+  BaseType_t xStatus;
+  const TickType_t xTicksToWait = pdMS_TO_TICKS( 1200 );
+   /* This task is also defined within an infinite loop. */
+   for( ;; )
+   {
+   /* This call should always find the queue empty because this task will
+   immediately remove any data that is written to the queue. */
+     if( uxQueueMessagesWaiting( xQueue ) != 0 )
+     {
+     vPrintString( "Queue should have been empty!\r\n" );
+     }
+     /* Receive data from the queue.
+     The first parameter is the queue from which data is to be received. The
+     queue is created before the scheduler is started, and therefore before this
+     task runs for the first time.
+     The second parameter is the buffer into which the received data will be
+     placed. In this case the buffer is simply the address of a variable that
+     has the required size to hold the received data.
+     The last parameter is the block time – the maximum amount of time that the
+     task will remain in the Blocked state to wait for data to be available
+     should the queue already be empty. */
+     xStatus = xQueueReceive( xQueue, &lReceivedValue, xTicksToWait );
+     if( xStatus == pdPASS )
+     {
+     /* Data was successfully received from the queue, print out the received
+     value. */
+       SERIAL_PORT.println(lReceivedValue );
+    
+     //vPrintStringAndNumber( "Received = ", lReceivedValue );
+     }
+     else
+     {
+       /* Data was not received from the queue even after waiting for 100ms.
+       This must be an error as the sending tasks are free running and will be
+       continuously writing to the queue. */
+        vPrintString( "Could not receive from the queue.\r\n" );
+     }
+   }
+}
+
+
+void setup() {
+    // put your setup code here, to run once;
+  
+    /* The queue is created to hold a maximum of 5 values, each of which is
+   large enough to hold a variable of type int32_t. */
+   xQueue = xQueueCreate( 5, sizeof( int32_t ) );
+   if( xQueue != NULL )
+   {
+   /* Create two instances of the task that will send to the queue. The task
+   parameter is used to pass the value that the task will write to the queue,
+   so one task will continuously write 100 to the queue while the other task
+   will continuously write 200 to the queue. Both tasks are created at
+   priority 1. */
+   xTaskCreate( vSenderTask, "Sender1", 1000, ( void * ) 100, 1, NULL );
+   xTaskCreate( vSenderTask, "Sender2", 1000, ( void * ) 200, 1, NULL );
+   /* Create the task that will read from the queue. The task is created with
+   priority 2, so above the priority of the sender tasks. */
+   xTaskCreate( vReceiverTask, "Receiver", 1000, NULL, 2, NULL );
+   /* Start the scheduler so the created tasks start executing. */
+   }
+   else
+   {
+   /* The queue could not be created. */
+   }
+
+}
+
+void loop() {
+ 
+}