Skeleton program for Federico's 4YP project.

Dependencies:   WebSocketClient WiflyInterface mbed messages

Fork of IoT_Ex by Damien Frost

Files at this revision

API Documentation at this revision

Comitter:
defrost
Date:
Tue Nov 29 15:02:01 2016 +0000
Parent:
9:9b6a54e63942
Commit message:
- Works

Changed in this revision

headers/Commands.h Show annotated file Show diff for this revision Revisions of this file
headers/globals.h Show annotated file Show diff for this revision Revisions of this file
headers/pwm.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
source/globals.cpp Show annotated file Show diff for this revision Revisions of this file
source/pwm.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 9b6a54e63942 -r e8b66718a103 headers/Commands.h
--- a/headers/Commands.h	Tue Nov 29 12:22:14 2016 +0000
+++ b/headers/Commands.h	Tue Nov 29 15:02:01 2016 +0000
@@ -74,13 +74,13 @@
 #define SF_SERVERCONNECTED      BIT0
 #define SF_AUTOCONNECT          BIT1        // Set this flag to automatically start connecting to the websocket server
 #define SF_WIRELESSCONNECTED    BIT2        // Flag to indicate whether or not the wireless network is connected
+#define SS_PWMOVERRUNFLAG       BIT3        // Flag to indicate when the PWM interrutp is still running
                                             
 // Wifi Commands
-#define     NO_WIFI_CMD         0
-#define     CV_LED_WIFI_CMD     1
+#define     NO_WIFI_CMD             0
+#define     CV_LED_WIFI_CMD         1
+#define     CV_PWM_PERIOD_US_CMD    2
 
-// Change variable commands:
-#define     CV_LED              1
 
 extern StatusReg IotStatus;
 
diff -r 9b6a54e63942 -r e8b66718a103 headers/globals.h
--- a/headers/globals.h	Tue Nov 29 12:22:14 2016 +0000
+++ b/headers/globals.h	Tue Nov 29 15:02:01 2016 +0000
@@ -48,6 +48,10 @@
 #define WS_PORT     4444
 #define SERVER_IP "192.168.1.99"
 
+// Pin assignments
+#define VOLTAGE_SENSOR_PIN  PA_0
+#define CURRENT_SENSOR_PIN  PA_1
+
 // Hardware:
 extern Serial          pc;
 extern InterruptIn     UIBut1;
@@ -59,8 +63,15 @@
 extern int SendCounter;
 extern int IoT_ID;
 extern float TempSensor;
+extern float VoltageMeasurement;
+extern float CurrentMeasurement;
+extern float PwmPeriod_us;
+extern float Duty_us;
 extern char* wifissid;
 extern char* wifipassword;
+extern DigitalOut      db;
+extern AnalogIn        VoltageSensor;
+extern AnalogIn        CurrentSensor;
 
 // Communication:
 extern WiflyInterface eth;
diff -r 9b6a54e63942 -r e8b66718a103 headers/pwm.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/headers/pwm.h	Tue Nov 29 15:02:01 2016 +0000
@@ -0,0 +1,96 @@
+// ************
+// * iQ_PWM.h *
+// ************
+//
+// Created: 2015/03/19
+// By: Damien Frost
+//
+// Description:
+// This file provides all of the functions used to configure the 
+// high speed PWM module of the STM32F401RE microcontroller.
+
+#ifndef PWWM_H
+#define PWWM_H
+
+#define SETUDIS     TIM1->CR1 |= TIM_CR1_UDIS
+#define CLEARUDIS   TIM1->CR1 &= ~TIM_CR1_UDIS
+#define PWMHIGHPRIORITY 0
+#define PWMLOWPRIORITY  1
+
+#define PS_RESET    0
+#define PS_SHIFT    1
+
+#define PWMST_SETUPCONV         0
+#define PWMST_STARTCONV         1
+#define PWMST_RUNSCSKDC         2
+#define PWMST_CALCNEWPH         3
+#define PWMST_SETNEWPH          4
+#define PWMST_SHIFT             5
+#define PWMST_SAMPLECHTROUGH    6
+#define PWMST_WAITSAMPLETROUGH  7    
+#define PWMST_WAIT              8
+#define PWMST_SAMPLECHHILL      9
+#define PWMST_WAITSAMPLEHILL    10
+#define PWMST_SKIPONECYCLE      11
+#define PWMST_MAXST             12
+
+#define PWMSTEP_US  (10.0f/839.0f)
+#define TS          (PWMPER_US/1000000)
+#define PWMARRMAX   (65535)
+
+
+
+// Global variables:
+extern float CurrentPhaseShift;
+extern unsigned int OneCycleSkipExitState;
+extern void (*const pwmsm_StateFunction [PWMST_MAXST]) (void);
+
+// Function prototypes:
+
+// Configures the PWM for use, using an initial duty cycle of 'duty'
+void ConfigurePWM(float duty_us, float period_us);
+
+// PWM ISR, used fo rdebugging purposes:
+void TIM1_CC_IRQHandler(void);
+
+// Configures the Dead time of the PWM, using an initial dead time of 'dt':
+void ConfigureDeadTime(float dt_ns);
+
+// Set duty by specifying the duty cycle in us:
+float SetDuty_us(float duty_us);
+
+// Set a new duty cycle by specifying it as a number between 0 and 1:
+float SetDuty(float duty);
+
+// This function checks to make sure the duty cycle is within the min and max constraints, it is called by the SetDuty functions.
+float CheckMinMaxDuty(float duty);
+
+// Turn on the the PWM signal:
+void TurnOnPWM(bool trueForOn);
+
+// Apply a phase shift:
+int PhaseShift(unsigned int cmd, float phase);
+
+// Set a new PWM Period:
+void SetPWMPeriodAndDuty(int pwmper);
+void SetPWMPeriodAndDuty_us(float period);
+
+// Set the time at which the PWM isr fires:
+void SetISRTime(unsigned int isrtime);
+
+// PWM State Machine functions:
+void pwmsm_SetupConv(void);         // PWMST_SETUPCONV          0
+void pwmsm_StartConv(void);         // PWMST_STARTCONV          1
+void pwmsm_RunScskdc(void);         // PWMST_RUNSCSKDC          2
+void pwmsm_CalcNewPh(void);         // PWMST_CALCNEWPH          3
+void pwmsm_SetNewPh(void);          // PWMST_SETNEWPH           4
+void pwmsm_Shift(void);             // PWMST_SHIFT              5
+void pwmsm_SampleChTrough(void);    // PWMST_SAMPLECHTROUGH     6
+void pwmsm_WaitSampleTrough(void);  // PWMST_WAITSAMPLETROUGH   7
+void pwmsm_Wait(void);              // PWMST_WAIT               8
+void pwmsm_SampleChHill(void);      // PWMST_SAMPLECHHILL       9
+void pwmsm_WaitSampleHill(void);    // PWMST_WAITSAMPLEHILL     10
+void pwmsm_SkipOneCycle(void);      // PWMST_SKIPONECYCLE       11
+void SetupOneCycleSkip(unsigned int nextState);
+
+#endif  /* PWWM_H */
diff -r 9b6a54e63942 -r e8b66718a103 main.cpp
--- a/main.cpp	Tue Nov 29 12:22:14 2016 +0000
+++ b/main.cpp	Tue Nov 29 15:02:01 2016 +0000
@@ -37,6 +37,7 @@
 #include "Commands.h"
 #include "Websocket.h"
 #include "ADC.h"
+#include "pwm.h"
 
 //#define DEBUG
 #define INFOMESSAGES
@@ -73,12 +74,17 @@
     // Connect to the wifi network. It will basically get stuck here until it
     // connects to the network.
     SetupNetwork(5000);
-    
+        
     // Configure the baud rate of the wifi shield:
     // This will make our wireless transmissions much faster.
     ws.setBaud(115200);
     wait(0.5f);
     
+    // Configure the PWM module:
+    ConfigurePWM(Duty_us, PwmPeriod_us);
+    // Turn on the PWM:
+    TurnOnPWM(true);
+    
     // Check to see we are connected to the network:
     if(IotStatus.CheckFlag(SF_WIRELESSCONNECTED)){
         // Try to connect to the WebSocket server:
diff -r 9b6a54e63942 -r e8b66718a103 source/globals.cpp
--- a/source/globals.cpp	Tue Nov 29 12:22:14 2016 +0000
+++ b/source/globals.cpp	Tue Nov 29 15:02:01 2016 +0000
@@ -32,8 +32,9 @@
 
 #include "mbed.h"
 #include "globals.h"
+#include "pwm.h"
 
-//#define DEBUG
+#define DEBUG
 #define INFOMESSAGES
 #define WARNMESSAGES
 #define ERRMESSAGES
@@ -51,8 +52,16 @@
 int SendCounter = 0;
 extern int IoT_ID = 0;
 float TempSensor = 0.0f;
+float VoltageMeasurement = 0.0f;
+float CurrentMeasurement = 0.0f;
+float PwmPeriod_us = 20.0f;
+float Duty_us = 10.0f;
 char* wifissid = "SC";
 char* wifipassword = "smartcellshield";
+DigitalOut      db(PC_10);
+AnalogIn        VoltageSensor(VOLTAGE_SENSOR_PIN);
+AnalogIn        CurrentSensor(CURRENT_SENSOR_PIN);
+
 
 // Wifily interface declaration:
 WiflyInterface eth(D8, D2, D6, LED1, wifissid, wifipassword, WPA2);
@@ -104,7 +113,7 @@
     int intresult;    
     
     if(IotStatus.CheckFlag(SF_SERVERCONNECTED)){
-        sprintf(msg_buffer, "%d,%d,%.5f", IoT_ID, SendCounter,TempSensor);
+        sprintf(msg_buffer, "%d,%d,%.5f,%.5f,%.5f,%.5f", IoT_ID, SendCounter,TempSensor, VoltageMeasurement, CurrentMeasurement, PwmPeriod_us);
         INFO("Sending: %s", msg_buffer);    // When this line is commented out, the mbed never tries to reconnect to the server after one try. SUPER. Keeping this here also uses precious CPU time
         intresult = ws.send(msg_buffer);
     }else{
@@ -170,6 +179,10 @@
                 // Get one more value:
                 sscanf(msg_buffer2, "%f", value);
             }
+            if(*wifi_cmd == CV_PWM_PERIOD_US_CMD){
+                // Get one more value:
+                sscanf(msg_buffer2, "%f", value);
+            }
         }else if(resp == -1){
             // Connection to the server is lost:
             IotStatus.ClearFlag(SF_SERVERCONNECTED);
@@ -185,13 +198,19 @@
 void ModifyVariable(unsigned int wifi_var, float wifi_data){
     // modifies something in the SCS Controller:
     switch(wifi_var){
-        case CV_LED:
+        case CV_LED_WIFI_CMD:
             if(wifi_data > 0){
                 Led = 1;
             }else{
                 Led = 0;
             }
             break;
+        case CV_PWM_PERIOD_US_CMD:
+            DBG("wifi_data: %.3f", wifi_data);
+            PwmPeriod_us = wifi_data;
+            SetPWMPeriodAndDuty_us(PwmPeriod_us);
+            break;
+            
         
         default:
             break;
diff -r 9b6a54e63942 -r e8b66718a103 source/pwm.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/pwm.cpp	Tue Nov 29 15:02:01 2016 +0000
@@ -0,0 +1,380 @@
+// **************
+// * iQ_PWM.cpp *
+// **************
+//
+// Created: 2015/03/19
+// By: Damien Frost
+
+#include "math.h"
+#include "mbed.h"
+#include "globals.h"
+#include "pwm.h"
+#include "ADC.h"
+#include "Commands.h"
+
+#define DEBUG
+#define INFOMESSAGES
+#define WARNMESSAGES
+#define ERRMESSAGES
+#define FUNCNAME "PWM"
+#include "messages.h"
+
+
+// Configures the PWM for use, using an initial duty cycle and period in us.
+void ConfigurePWM(float duty_us, float period_us){
+    unsigned int value;
+    float newVal;
+    
+    // Ensure power is turned on
+    // Grabbed from lines 54-57 of analogin_api.h, modified for PWM
+    // This turns on the clock to Ports A, B, and C
+    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
+    // This turns on the clock to the Time 1:
+    RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
+    
+    // Set the GPIO Ports properly:
+    // PWM1 is connected to  PA_8
+    // PWM1N is connected to PA_7
+    
+    // Set the PWM outputs to general output pins:
+    // This sets the PA_7 and PA_8 pins to Alternate Function Pins
+    value = 0x8000 + 0x20000;
+    GPIOA->MODER |= value;
+    
+    // Set the PWM outputs to high speed:
+    value = 0xC000 + 0x30000;
+    GPIOA->OSPEEDR |= value;
+    
+    // Set PWM as outputs to the pins:
+    value = GPIOA->AFR[1];
+    // Reset the lowest four bits:
+    value &= 0xFFFFFFF0;
+    // Configure PA_8 to AF:
+    value |= 0x1;
+    GPIOA->AFR[1] = value;
+    
+    value = GPIOA->AFR[0];
+    // Reset the the 4 MSB:
+    value &= 0x0FFFFFFF;
+    // Configure PA_7 to AF:
+    value |= 0x10000000;
+    GPIOA->AFR[0] = value;
+    
+    // Set pull down resistors to PWM outputs:
+    value = GPIOA->PUPDR;
+    // Clear the bits:
+    value &= ~(GPIO_PUPDR_PUPDR7 | GPIO_PUPDR_PUPDR8);
+    // Set to pull down:
+    value |= GPIO_PUPDR_PUPDR7_1 | GPIO_PUPDR_PUPDR8_1;
+    // Set the register:
+    GPIOA ->PUPDR = value;
+    
+    // Set the prescale value to 1:
+    TIM1->PSC = 0;
+    
+    // *** TIM1 control register 1: TIMx_CR1 ***
+    value = 0;
+    // [9:8] Set CKD bits to zero for clock division of 1
+    // [7] TIMx_ARR register is buffered, set the ARPE bit to 1:
+    value |= TIM_CR1_ARPE;
+    // [6:5] Set CMS bits to zero for edge aligned mode
+    // [6:5] Set CMS bits to 10 for Center Aligned mode 2, up down mode with flags set when counter reaches the top.
+    //value |= TIM_CR1_CMS_1;
+    // [4] Set DIR bit to zero for upcounting
+    // [3] Set OPM bit to zero so that the counter is not stopped at update event
+    // [2] Set URS bit to zero so that anything can create an interrupt
+    // [1] Set UDIS bit to zero to generate an update event
+    // [0] Set the CEN bit to zero to disable the counter
+    // * Set the TIMx_CR1 Register: *
+    TIM1->CR1 |= value;
+    
+    // *** TIM1 control register 2: TIMx_CR2 ***
+    value  = 0;
+    // [14] Set OIS4 bit to zero, the idle state of OC4 output
+    // [13] Set OIS3N bit to zero, the idle state of OC3N output
+    // [12] Set OIS3 bit to zero, the idle state of OC3 output
+    // [11] Set OIS2N bit to zero, the idle state of OC2N output
+    // [10] Set OIS2 bit to zero, the idle state of OC2 output
+    // [9] Set OIS1N bit to zero, the idle state of OC1N output
+    // [8] Set OIS1 bit to zero, the idle state of OC1 output
+    // [7] Set TI1S bit to zero, connecting only CH1 pin to TI1 input
+    // [6:4] Set to 111: The OC4REF signal is used as trigger output (TRGO)
+    // value |= TIM_CR2_MMS_2 | TIM_CR2_MMS_1 | TIM_CR2_MMS_0;
+    //value |= TIM_CR2_MMS_1 | TIM_CR2_MMS_0;
+    // [3] Set CCDS bit to zero, request sent when CCx event occurs
+    // [2] Set CCUS bit to 1, capture/compare control bits are updated by setting the COMG bit or when a rising edge occurs on TRGI
+    //value |= 0x4;
+    // [0] Set CCPC bit to 1, CCxE, CCxNE and OCxM are update on a commutation event, or rising edge on TRGI
+    //value |= 0x1;
+    // * Set the TIMx_CR2 Register: *
+    TIM1->CR2 = value;
+    
+    // *** TIM1 Auto Reload Register: ARR ***
+    value = 0;
+    // [15:0] Set ARR bits to the frequency to be loaded in:
+    newVal = ceil(period_us/PWMSTEP_US);
+    value = (unsigned int) newVal;
+    // * Set the TIMx_ARR Register:
+    TIM1->ARR = value;
+    
+    // *** TIM1 capture/compare register 1: CCR1 ***
+    value = 0;
+    // [15:0] Set the capture compare value to the duty cycle:
+    newVal = ceil(duty_us/PWMSTEP_US);
+    value = (unsigned int) newVal;
+    // * Set the TIMx_CCR1 Register:
+    TIM1->CCR1 = value;
+    
+    // *** TIM1 capture/compare register 4: CCR4 ***
+    value = 0;
+    // [15:0] Set the capture compare value to the value at which the PWM interrupt should be triggered:
+    newVal = 0;
+    value = (unsigned int) newVal;
+    // * Set the TIMx_CCR4 Register:
+    TIM1->CCR4 = 0;
+    
+    // *** TIM1 capture/compare mode register 2: CCMR2
+    value = 0;
+    // [15] Set OC4CE bit to 0, OC4Ref is not affected by the ETRF input
+    // [14-12] Set the OC4M bits to '110', PWM mode 1, which is what we want I think.
+    value |= TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4M_1;
+    // [11] Set the OC4PE bit to 1, meaning read/write operations to the preload event require an update event.
+    value |= TIM_CCMR2_OC4PE;
+    // [10] Set the OC4FE bit to 0, the output compare fast enable is disabled
+    // [9:8] Set the CC4S bits to 0, the channel is configured as an output.
+    // * Set the TIMx_CCMR2 Register: *
+    TIM1->CCMR2 = value;
+    
+    // *** TIM1 capture/compare mode register 1: CCMR1
+    value = 0;
+    // [7] Set OC1CE bit to 0, OC1Ref is not affected by the ETRF input
+    // [6-4] Set the OC1M bits to '110', PWM mode 1, which is what we want I think.
+    value |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
+    // [3] Set the OC1PE bit to 1, meaning read/write operations to the preload event require an update event.
+    value |= TIM_CCMR1_OC1PE;
+    // [2] Set the OC1FE bit to 0, the output compare fast enable is disabled
+    // [1:0] Set the CC1S bits to 0, the channel is configured as an output.
+    // * Set the TIMx_CCMR1 Register: *
+    TIM1->CCMR1 = value;
+    
+    // *** TIM1 capture/compare enable register: CCER
+    value = 0;
+    // [15:4] - Don't care:
+    // [3] Set CC1NP bit to 1 for active low. (
+    value |= TIM_CCER_CC1NP;
+    // [2] Set CC1NE bit to 0, to de-activate the OC1N signal
+    // value |= 0x4;
+    // [1] Set the CC1P bit to 1 for active low.
+    value |= TIM_CCER_CC1P;
+    // [0] Set the CC1E bit to 1, to de-activate the OC1 signal
+    // value |= 0x1;
+    // * Set the TIM1_CCER Register: *
+    TIM1->CCER = value;
+    
+    // *** TIM1 break and dead-time register: BDTR
+    value = 0;
+    // [15] Set MOE bit to 1 to enable the OC and OCN outputs
+    value |= 0x8000;
+    // [11] Set the OSSR bit such that the ouputs are forced to their idle mode when not running
+    //value |= TIM_BDTR_OSSR;
+    // [10] Set OSSI bit such that the outputs are forced to their idle mode when MOE = 0
+    value |= TIM_BDTR_OSSI;
+    // * Set the TIM1_BDTR register:
+    TIM1->BDTR = value;
+    
+    // *** TIM1 DMA/Interrupt enable register: DIER
+    value = 0;
+    // [2] Set the CC1IE bit to 1, to trigger an interrupt when counter 1 has a match - which should be half way through the duty cycle.
+    value |= TIM_DIER_CC4IE;
+    // Set the TIM1_DIER register:
+    TIM1->DIER |= value;
+    
+    // Set the UG bit in the EGR register to kick things off:
+    value = 3;
+    TIM1->EGR = value;
+    
+    // Print a message saying you are done:
+    INFO("PWM configuration complete!");
+    
+    #ifdef DEBUG_PWM
+        // Debugging Code:
+        DBG("TIM1 Registers:");
+        DBG("The CCMR1 Register reads: %d", TIM1->CCMR1);
+        DBG("The CR1 Register reads: %d", TIM1->CR1);
+        DBG("The CR2 Register reads: %d", TIM1->CR2);
+        DBG("The ARR Register reads: %d", TIM1->ARR);
+        DBG("The CCR1 Register reads: %d", TIM1->CCR1);
+        DBG("The CCER Register reads: %d", TIM1->CCER);
+        DBG("The BDTR Register reads: %d", TIM1->BDTR);
+        DBG("The EGR Register reads: %d", TIM1->EGR);
+        DBG("The SMCR Register reads: %d", TIM1->SMCR);
+        DBG("The PSC Register reads: %d", TIM1->PSC);
+        DBG("The GPIOA Registers:\n\r");
+        DBG("The MODER Register reads: %d", GPIOA->MODER);
+        DBG("The OSPEEDR Register reads: %d", GPIOA->OSPEEDR);
+        DBG("The AFR[0] Register reads: %d", GPIOA->AFR[0]);
+        DBG("The AFR[1] Register reads: %d", GPIOA->AFR[1]);
+        DBG("Clock Registers:");
+        DBG("The CFGR Register reads: %d", RCC->CFGR);
+        
+    #endif
+    
+    INFO("TIM1 Interrupt Priority: %d", NVIC_GetPriority(TIM1_CC_IRQn));
+    INFO("UART1 Interrupt Priority: %d", NVIC_GetPriority(USART1_IRQn));
+    INFO("UART2 Interrupt Priority: %d", NVIC_GetPriority(USART2_IRQn));
+    INFO("UART6 Interrupt Priority: %d", NVIC_GetPriority(USART6_IRQn));
+    
+    // Configure the interrupt:
+    NVIC_SetVector(TIM1_CC_IRQn, (uint32_t)&TIM1_CC_IRQHandler);
+    NVIC_SetPriority(TIM1_CC_IRQn, PWMHIGHPRIORITY);
+    NVIC_EnableIRQ(TIM1_CC_IRQn);
+    
+    
+
+    return;
+}
+
+void TIM1_CC_IRQHandler(void){
+    
+    // States of the PWM module:
+    /*
+    #define PWMST_SETUPCONV 0
+    #define PWMST_STARTCONV 1
+    #define PWMST_RUNSCSKDC 2
+    #define PWMST_CALCNEWPH 3
+    #define PWMST_SETNEWPH  4
+    #define PWMST_SHIFT     5
+    #define PWMST_SAMPLECHTROUGH    6
+    #define PWMST_WAITSAMPLETROUGH  7    
+    #define PWMST_WAIT              8
+    #define PWMST_SAMPLECHHILL      9
+    #define PWMST_WAITSAMPLEHILL    10
+    #define PWMST_MAXST             11
+    */
+    
+    if(((TIM1->SR & TIM_SR_CC4IF) > 0)&&(IotStatus.CheckFlag(SS_PWMOVERRUNFLAG) == false)){
+        // Block any other interrupts from occuring:
+        IotStatus.SetFlag(SS_PWMOVERRUNFLAG);
+        
+        db = 1;
+        
+        // Sample the ADCs:
+        VoltageMeasurement = VoltageSensor.read();
+        CurrentMeasurement = CurrentSensor.read();
+        db = 0;
+        // Set battery model inputs:
+        
+        
+        // Set a debug pin high:
+        db = 1; // Probe this pin to see how long the battery model algorithm takes to run.
+        
+        // Run battery model here:
+        
+        
+        // Clear the debug pin:
+        db = 0;
+        
+        // Read battery model outputs:
+        
+        
+        
+        // Clear the flag:
+        IotStatus.ClearFlag(SS_PWMOVERRUNFLAG);
+        TIM1->SR &= (~TIM_SR_CC4IF);
+    }
+    
+    
+    return;
+}
+
+    
+
+
+
+// Set a new duty cycle:
+float SetDuty_us(float duty_us){
+    unsigned int value;
+    float newVal;
+    float temp = (duty_us/PwmPeriod_us);
+        
+    newVal = ceil(duty_us/PWMSTEP_US);
+    value = (unsigned int) newVal;
+    // Disable the Update Event:
+    SETUDIS;
+    // * Set the TIMx_CCR1 Register:
+    TIM1->CCR1 = value;
+    // Set the CCR4 Register to the maximum value minus CH4SHIFT. This ensures the high speed ADC is in sync with the PWM module.
+    TIM1->CCR4 = 0;
+    // Re-enable the update event
+    CLEARUDIS;
+    return temp*PwmPeriod_us;
+}
+
+
+// Turns on and off the PWM:
+void TurnOnPWM(bool trueForOn){
+    if(trueForOn){ 
+        // Enable the outputs:
+        DBG("Enabling outputs...");
+        TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC1NE;
+        // Turn on the gating:
+        DBG("Turning on gating...:");
+        TIM1->CR1 |= TIM_CR1_CEN;
+        DBG("PWM on.");
+        
+    }else{
+        // Turn off the gating:
+        TIM1->CR1 &= ~TIM_CR1_CEN;
+        // Disable the outputs:
+        TIM1->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC1NE);
+    }
+    return;
+}
+        
+
+        
+void SetPWMPeriodAndDuty(int pwmper){
+    // This functions sets the PWM period by first disabling updates to the PWM module
+    // It also scales the duty cycle register, so the duty cycle is the SAME.
+    
+    // Disable the UEV event in the PWM module:
+    SETUDIS;
+    // Set the new period:
+    TIM1->ARR = (unsigned int)(PwmPeriod_us/PWMSTEP_US);
+    // Set the new duty cycle:
+    TIM1->CCR1 = ((unsigned int)(Duty_us/PwmPeriod_us * TIM1->ARR));
+    // Set the CCR4 Register to the maximum value minus CH4SHIFT. This ensures the high speed ADC is in sync with the PWM module.
+    TIM1->CCR4 = 0;
+    // Re-enable the UEV event:
+    CLEARUDIS;
+    // Done!
+    return;
+}
+
+void SetPWMPeriodAndDuty_us(float period){
+    // This functions sets the PWM period by first disabling updates to the PWM module
+    // It also scales the duty cycle register, so the duty cycle is the SAME.
+    float PwmSteps = ((float)period/(float)PWMSTEP_US);
+    
+    // Disable the UEV event in the PWM module:
+    SETUDIS;
+    // Set the new period:
+    if(PwmSteps > PWMARRMAX){
+        PwmSteps = PWMARRMAX;
+        WARN("Maximum PWM Period Reached.");
+    }
+    TIM1->ARR = (unsigned int)(PwmSteps);
+    DBG("TIM1->ARR: %d", TIM1->ARR);
+    DBG("period: %.3f", period);
+    DBG("PWMSTEP: %.3f", (float) PWMSTEP_US);
+    // Set the new duty cycle:
+    TIM1->CCR1 = ((unsigned int)(Duty_us/period * TIM1->ARR));
+    // Set the CCR4 Register to the maximum value minus CH4SHIFT. This ensures the high speed ADC is in sync with the PWM module.
+    TIM1->CCR4 = 0;
+    // Re-enable the UEV event:
+    CLEARUDIS;
+    // Done!
+    return;
+}
+
+