MKR Zero - temp fan, volt display and message board for peripheral uCon Project

Hi all,
I have a HUMS project using the Arduino MKR Zero. The project consists of:

  • Arduino MKR Zero
  • 4 Pin fan (rated at 25kHz)
  • 4x20 character I2C LCD Display
  • Temperature sensor (ds2401)

The requirements of the project include (3 parts):

Part 1.

  • To read the temperature
  • To influence the PWM of the fan based on the current temperature (set the scaling)

Part 2.

  • To measure 2 different external voltages on the Arduino (5V and 12V (using potential dividers))
  • To display these voltages on the LCD Display

Part 3.

  • To allow a pc controller (K66F) to communicate to the MKRZero (UART) and in turn influence 2 lines on the LCD display

Issues I’m having currently, if someone could give us a hand:

  • I’m struggling to set the frequency using the SAMD registers on a pin to 25kHz.

Questions:
Has anyone undertaken a similar project using the MKR Zero, with some advice.
PS. I have little experience with Arduino (firmware generally), however i’m challenging myself to learn

Setting the fan frequency to 25kHz (bit of code I found online)

void setup()
{
** REG_GCLK_GENDIV = GCLK_GENDIV_DIV(3) | // Divide the 48MHz clock source by divisor 3: 48MHz/3=16MHz**
** GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4**
** while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization**
** REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW**
** GCLK_GENCTRL_GENEN | // Enable GCLK4**
** GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source**
** GCLK_GENCTRL_ID(4); // Select GCLK4**
** while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization**
** // Enable the port multiplexer for the 4 PWM channels: timer TCC0 outputs**
** const uint8_t CHANNELS = 4;**
** const uint8_t pwmPins = { 2, 5, 6, 7 };**
** for (uint8_t i = 0; i < CHANNELS; i++)**
** {**
PORT->Group[g_APinDescription[pwmPins].ulPort].PINCFG[g_APinDescription[pwmPins*].ulPin].bit.PMUXEN = 1;
_
}
// Connect the TCC0 timer to the port outputs - port pins are paired odd PMUO and even PMUXE*
* // F & E specify the timers: TCC0, TCC1 and TCC2*
* PORT->Group[g> 1].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F;
PORT->Group[g_APinDescription[6].ulPort].PMUX[g_APinDescrip_APinDescription[2].ulPort].PMUX[g_APinDescription[2].ulPin >// Output 50Hz PWM on timer TCC0 (14-bit resolution)*

void setup()
{
* REG_GCLK_GENDIV = GCLK_GENDIV_DIV(3) | // Divide the 48MHz clock source by divisor 3: 48MHz/3=16MHz*
* GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4*
* while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization*
* REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW*
* GCLK_GENCTRL_GENEN | // Enable GCLK4*
* GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source*
* GCLK_GENCTRL_ID(4); // Select GCLK4*
* while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization*
* // Enable the port multiplexer for the 4 PWM channels: timer TCC0 outputs*
* const uint8_t CHANNELS = 4;
const uint8_t pwmPins[] = { 2, 5, 6, 7 };
for (uint8_t i = 0; i < CHANNELS; i++)*

* {_
PORT->Group[g_APinDescription[pwmPins].ulPort].PINCFG[g_APinDescription[pwmPins].ulPin].bit.PMUXEN = 1;
_ }
// Connect the TCC0 timer to the port outputs - port pins are paired odd PMUO and even PMUXE*

* // F & E specify the timers: TCC0, TCC1 and TCC2*
* PORT->Group[g_APinDescription[2].ulPort].PMUX[g_APinDescription[2].ulPin >> 1].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F;
PORT->Group[g_APinDescription[6].ulPort].PMUX[g_APinDescription[6].ulPin >> 1].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F;*

* // Feed GCLK4 to TCC0 and TCC1*
* REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TCC0 and TCC1*
* GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4*
* GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1*
* while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization*
* // Dual slope PWM operation: timers countinuously count up to PER register value then down 0*
* REG_TCC0_WAVE |= TCC_WAVE_POL(0xF) | // Reverse the output polarity on all TCC0 outputs*
* TCC_WAVE_WAVEGEN_DSBOTTOM; // Setup dual slope PWM on TCC0*
* while (TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization*
* // Each timer counts up to a maximum or TOP value set by the PER register,
// this determines the frequency of the PWM operation:
// 20000 = 50Hz, 10000 = 100Hz, 2500 = 400Hz, 40 = 25kHz*

* REG_TCC0_PER = 40; // Set the frequency of the PWM on TCC0 to 50Hz*
* while(TCC0->SYNCBUSY.bit.PER);
// The CCBx register value corresponds to the pulsewidth in microseconds (us)_

REG_TCC0_CCB0 = 1500; // TCC0 CCB0 - center the servo on D2*
* while(TCC0->SYNCBUSY.bit.CCB0);*
* REG_TCC0_CCB1 = 1500; // TCC0 CCB1 - center the servo on D5*
* while(TCC0->SYNCBUSY.bit.CCB1);*
* REG_TCC0_CCB2 = 1500; // TCC0 CCB2 - center the servo on D6*
* while(TCC0->SYNCBUSY.bit.CCB2);*
* REG_TCC0_CCB3 = 1500; // TCC0 CCB3 - center the servo on D7*
* while(TCC0->SYNCBUSY.bit.CCB3);*
* // Divide the 16MHz signal by 8 giving 2MHz (0.5us) TCC0 timer tick and enable the outputs*
* REG_TCC0_CTRLA |= TCC_CTRLA_PRESCALER_DIV8 | // Divide GCLK4 by 8*
* TCC_CTRLA_ENABLE; // Enable the TCC0 output*
* while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization*
}
void loop() { }
tion[6].ulPin >> 1].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F;
* // Feed GCLK4 to TCC0 and TCC1*
* REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TCC0 and TCC1*
* GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4*
* GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1*
* while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization*
* // Dual slope PWM operation: timers countinuously count up to PER register value then down 0*
* REG_TCC0_WAVE |= TCC_WAVE_POL(0xF) | // Reverse the output polarity on all TCC0 outputs*
* TCC_WAVE_WAVEGEN_DSBOTTOM; // Setup dual slope PWM on TCC0*
* while (TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization*
* // Each timer counts up to a maximum or TOP value set by the PER register,*
* // this determines the frequency of the PWM operation:*
* // 20000 = 50Hz, 10000 = 100Hz, 2500 = 400Hz*
* REG_TCC0_PER = 100; // Set the frequency of the PWM on TCC0 to 10000Hz*
* while(TCC0->SYNCBUSY.bit.PER);*
* // The CCBx register value corresponds to the pulsewidth in microseconds (us)*
* REG_TCC0_CCB0 = 1500; // TCC0 CCB0 - center the servo on D2*
* while(TCC0->SYNCBUSY.bit.CCB0);*
* REG_TCC0_CCB1 = 1500; // TCC0 CCB1 - center the servo on D5*
* while(TCC0->SYNCBUSY.bit.CCB1);*
* REG_TCC0_CCB2 = 1500; // TCC0 CCB2 - center the servo on D6*
* while(TCC0->SYNCBUSY.bit.CCB2);*
* REG_TCC0_CCB3 = 1500; // TCC0 CCB3 - center the servo on D7*
* while(TCC0->SYNCBUSY.bit.CCB3);*
* // Divide the 16MHz signal by 8 giving 2MHz (0.5us) TCC0 timer tick and enable the outputs*
* REG_TCC0_CTRLA |= TCC_CTRLA_PRESCALER_DIV8 | // Divide GCLK4 by 8*
* TCC_CTRLA_ENABLE; // Enable the TCC0 output*
* while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization*
}
void loop() { }[/b]

Does the fan have a 5v internal pullup on the PWM in?
If so, you might want to consider protecting the MKR Zero output pin.