Question re: analogWriteFrequency command

Status
Not open for further replies.

Constantin

Well-known member
Hi,

If I invoke the analogWriteFrequency command on a Teensy 3.0, does the affected pin just keep cycling ad infinitum until it's told to stop? (I presume so)

Does this cycling consume any ongoing CPU overhead or are the circuits responsible for PWM functions a separate, independent part of the ARM CPU, like the ADC is on a Atmega328?

Secondly, what is the maximum frequency with just 1-bit resolution (on or off)? I see 12MHz in the analogwrite page, but that is with 2 bits of resolution. I only need to drive the OSC circuit on an attached analog front end and having a pin drive it actively would be really neat (adjustable sampling rate, simpler PCB, lower cost, etc.)

Lastly, if I were to connect this to a MCP3911 with a OSC1/CLK input, would it be good design practice to install a current-limiting resistor between the two, and if so, what type would you recommend?
 
If I invoke the analogWriteFrequency command on a Teensy 3.0, does the affected pin just keep cycling ad infinitum until it's told to stop? (I presume so)

Yes. Actually, analogWriteFrequency() only configures which frequency will be produced. You then use analogWrite() to actually write to the pin.

Does this cycling consume any ongoing CPU overhead or are the circuits responsible for PWM functions a separate, independent part of the ARM CPU, like the ADC is on a Atmega328?

The PWM is generated by hardware, so there's no CPU overhead while it's running.

Secondly, what is the maximum frequency with just 1-bit resolution (on or off)? I see 12MHz in the analogwrite page, but that is with 2 bits of resolution. I only need to drive the OSC circuit on an attached analog front end and having a pin drive it actively would be really neat (adjustable sampling rate, simpler PCB, lower cost, etc.)

24 MHz might work. Why don't you give it a try and see? You may have to use 128 or 127 as the value in analogWrite/

Lastly, if I were to connect this to a MCP3911 with a OSC1/CLK input, would it be good design practice to install a current-limiting resistor between the two, and if so, what type would you recommend?

If the MCP3911 is running from the same 3.3 volt supply, then a resistor probably isn't necessary.

However, a 100 ohm resistor might be nice to reduce the amount of 24 MHz RF energy that might escape, to the extent the wire between Teensy3 and the MCP3911 acts like an antenna. Placing the ground wire physically close is the best way to keep it from acting like an antenna.
 
Hi Paul,

Thank you so much for the response, I will try it out, as my board is already borked to bits. However, my max input frequency is 16MHz, which I gather I cannot attain due to there not being a clean divisor. However, even 12MHz is pretty awesome, i.e. 3x faster than default and more importantly, adjustable. So, if the chip is only stable at 4MHz to start with before being ramped up to higher speeds (via boost setting) then the MCU allows me to do that.

Thank you again for your help.
 
A couple of observations from the trenches...

So I tried enabling the PWM on Pin 6 in the setup() function and expected it to carry over as implied above. Not so. PWM started in the setup() function does not carry over and is disabled when the Teensy switches over to loop(). So you have explicitly enable the PWM in loop(). This is an unfortunate behavior, IMO, as it would be great to be able to call for oscillator-like signal to be setup once in setup() and then being able to forget about it. As it stands, one either re-enables the PWM over and over in loop(), uses a conditional statement to detect a running oscillator, or builds a nested loop function such that the initial section with the PWM enable is never executed twice. There may be very good reasons for disabling PWM from setup() to loop() (and I don't know them) but it might be worth considering allowing PWM to continue from setup() into loop().
 
I don't understand. As a quick sanity check, I tried this. A 25 kHz waveform is on pin 6.

Code:
void setup() {
  analogWriteFrequency(6, 25000);
  analogWrite(6, 120);
}
void loop() {
}
 
Weird.

When I tried it on my Teensy 3, the PWMs on pin 6 only happened during the setup phase, then stopped when the MCU started executing the loop (). This is per my Saleae logic 8. Maybe Mr. Nyquist came by to kick me in the butt re: measuring a 12MHz signal with a 24MHz LA. I'll redo the example at a much lower frequency and report back. Thanks again.
 
Reproduced the problem...

If you can reproduce the problem, please post the code and I'll take a look at it next week.

Hi Paul,

Thank you for your kind offer. Below is my code to date. FWIW, there is no SQW output during setup at all now. Only if I enable it in loop(). Perhaps my single bit resolution setup is confusing the compiler? Many thanks for your help to date!

Code:
// SPI Stuff here
#include "SPI.h"
const uint8_t MCP3911_CS = 9; // Teensy SPI CS1 = MCP3911
const uint8_t SD_Card_CS = 10; // Teensy CS0 = SD Card
const uint8_t MCP3911_DR = 2; // Input for Data Ready Signal from MCP3911
const uint8_t MCP3911_CLK = 6; // Teensy CLK Signal output for MCP3911 OSC1 input

int16_t Volts,Current;
volatile uint8_t MCP3911_Data_Ready=0;

void setup() {

  //SPI Bus setup
  digitalWrite(MCP3911_CS,HIGH); //
  pinMode (MCP3911_CS, OUTPUT); // MCP3911
  pinMode (SD_Card_CS, OUTPUT); // SD Card

  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);
  SPI.setClockDivider(SPI_CLOCK_DIV2); //i.e. 8MHz on a Teensy running at 48MHz. 
  SPI.begin();

  pinMode (MCP3911_DR, INPUT_PULLUP); //Data Ready Pin on MCP3911 for later use in interrupt
  attachInterrupt(MCP3911_DR,MCP3911_Data_Ready_ISR,FALLING);

    //setup CLK function on Pin 6 to put CLK signal into MCP3911 OSC1 input
  pinMode (MCP3911_CLK, OUTPUT); // MCP3911 OSC1 input
  //analogWriteResolution(1);//make it single-bit only (need a SQW)
  //analogWrite(MCP3911_CLK, 1); //now make it run 
  //analogWriteFrequency(MCP3911_CLK, 1000000); //for 1MHz SQW operation

  //Setup Serial Comms
  Serial.begin(115200);

  delay(1000); //give me 1s to get serial monitor set up

  //Now setup the ADC - produces diagnostics
  Initial_ADC_Setup(); 

}

void loop()
{
  //in beginning, ensure 12MHz Master Clock
  analogWriteResolution(1);//make it single-bit only (need a SQW)
  analogWrite(MCP3911_CLK, 1); //now make it run 
  analogWriteFrequency(MCP3911_CLK, 12000000); //for 12MHz SQW operation
  int i=0;
  uint32_t nextsecond=millis()+1000UL;

  while (millis()<nextsecond) {
    if (MCP3911_Data_Ready>0)
    {
      read_VI_from_MCP3911();
      Serial.print("Volts: ");
      Serial.print(Volts);
      Serial.print(" - Current: ");
      Serial.println(Current);
      i++;
      MCP3911_Data_Ready=0;
    }

  }
  Serial.print("Samples/s: ");
  Serial.println(i);
}


void MCP3911_Data_Ready_ISR ()
{ 
  MCP3911_Data_Ready++;
}


//SPI function to see if data is ready, alternative to intrrupt approach using MCP3911_DR pin 
uint8_t Is_MCP3911_Data_Ready ()
{
  /* R/W Status and Communication Register (Read / Write)
   Address: 0x0A - 16 bits 
   bit 15:14 MODOUT<1:0>: Modulator Output Setting for MDAT pins
   11 = Both CH0 and CH1 modulator outputs are present on MDAT1 and MDAT0 pins, both SINC fil- ters are off, no data ready pulse is present
   10 = CH1 ADC Modulator output present on MDAT1 pin, SINC filter on channel 1 is off, data ready pulse from channel 1 is not present on DR pin
   01 = CH0 ADC Modulator output present on MDAT0 pin, SINC filter on channel 0 is off, data ready pulse from channel 0 is not present on DR pin
   *00 = No Modulator output is enabled, SINC filters are on, data readys are present on DR pin for both channels (DEFAULT)
   
   bit 13  Unimplemented, read as 0
   
   bit 12  DR_HIZ: Data Ready Pin Inactive State Control
   1 = The DR pin state is a logic high when data is NOT ready
   *0 = The DR pin state is high impedance when data is NOT ready(DEFAULT)
   
   bit 11:10 DRMODE<1:0>: Data Ready Pin (DR) mode configuration bits
   11 = Both Data Ready pulses from CH0 and CH1 are output on DR pin
   10 = Data Ready pulses from CH1 ADC are output on DR pin. Data ready pulses from CH0 are not present on the DR pin.
   01 = Data Ready pulses from CH0 ADC are output on DR pin. Data ready pulses from CH1 are not present on the DR pin.
   *00 = Data Ready pulses from the lagging ADC between the two are output on DR pin. The lagging ADC depends on the PHASE register and on the OSR. (DEFAULT) 
   
   bit 9:8 DRSTATUS<1:0>: Data Ready Status
   *11 = ADC Channel 1 and Channel 0 data not ready (DEFAULT)
   10 = ADC Channel 1 data not ready, ADC Channel 0 data ready 
   01 = ADC Channel 0 data not ready, ADC Channel 1 data ready 
   00 = ADC Channel 1 and Channel 0 data ready
   */

  uint8_t i = Read_MCP3911_Register(0x0A); // send address with read command to MCP3911
  i = i & B00000011; //strip out stuff not needed
  return i;
}


//read Current and Voltage results from MCP3911
void read_VI_from_MCP3911()
{

  digitalWrite(MCP3911_CS, LOW); // now take CS low to enable SPI device
  SPI.transfer(0x01); // send 0x00 address with read command to MCP3911
  //now ask for data
  //Volts = SPI.transfer(0x00)<<24;
  Volts = SPI.transfer(0x00)<<8;
  Volts |= SPI.transfer(0x00);

  //Current = SPI.transfer(0x00)<<24;
  Current = SPI.transfer(0x00)<<8;
  Current |= SPI.transfer(0x00);
  digitalWrite(MCP3911_CS, HIGH); // deselect the CS pin. 

  //Volts >>= 8; // now get the sign right ===> Convert from 24bit number to signed 32bit int.
  //Current >>= 8; // now get the sign right ===> Convert from 24bit number to signed 32bit int. 

}

void Initial_ADC_Setup()
{  

  // First Put ADC into Reset Mode
  /*
   bit 7:6 RESET<1:0>: Reset mode setting for ADCs
   11 = Both CH0 and CH1 ADC are in reset mode 
   10 = CH1 ADC in reset mode
   01 = CH0 ADC in reset mode
   *00 = Neither ADC in reset mode(default)
   
   bit5:4 SHUTDOWN<1:0>: Shutdown mode setting for ADCs
   11 = Both CH0 and CH1 ADC in Shutdown 
   10 = CH1 ADC in Shutdown
   01 = CH0 ADC in Shutdown
   *00 = Neither Channel in Shutdown(default)
   
   bit 3: Not implemented, read as 0
   
   bit 2: VREFEXT Internal Voltage Reference Shutdown Control 
   1 = Internal Voltage Reference Disabled
   *0 = Internal Voltage Reference Enabled (Default)
   
   bit 1: CLKEXT Internal Clock selection bits
   *1 = External clock drive by MCU on OSC1 pin (crystal oscillator disabled, no internal power consumption) (Default)
   0 = Crystal oscillator is enabled. A crystal must be placed between OSC1 and OSC2 pins.
   
   bit 0: Not implemented, read as 0
   */

  Write_MCP3911_Register (0x0D, B11000010); 

  /* Phase Register  (Read / Write)
   Address: 0x07 - 16 bits
   
   bit 15:12 Unimplemented, read as ‘0’
   bit 11:0 CH0 relative to CH1 phase delay 
   Delay = PHASE Register’s two’s complement code/DMCLK (Default PHASE = 0).
   
   Write_MCP3911_Register (0x07, B00000000);
   Write_MCP3911_Register (0x08, B00000000);
   
   since no phase delay is programmed at present, leave out
   */

  /* R/W Gain and Boost Configuration Register (Read / Write)
   Address: 0x09 - 8 bits
   
   bit 7:6 BOOST<1:0> Bias Current Selection
   *11 = Both channels have current x 2
   10 = Both channels have current x 1(DEFAULT)
   01 = Both channels have current x 0.66
   00 = Both channels have current x 0.5
   
   bit 5:3 PGA_CH1<2:0>: PGA Setting for Channel 1 
   111 = Reserved (Gain = 1)
   110 = Reserved (Gain = 1)
   101 = Gain is 32
   100 = Gain is 16
   011 = Gain is 8
   010 = Gain is 4
   001 = Gain is 2
   *000 = Gain is 1 (DEFAULT)
   
   bit 2:0 PGA_CH0<2:0>: PGA Setting for Channel 0
   111 = Reserved (Gain = 1)
   110 = Reserved (Gain = 1)
   101 = Gain is 32
   100 = Gain is 16
   011 = Gain is 8
   010 = Gain is 4
   001 = Gain is 2
   *000 = Gain is 1 (DEFAULT)
   */

  Write_MCP3911_Register (0x09, B11000000);

  /* R/W Status and Communication Register (Read / Write)
   Address: 0x0A - 16 bits 
   bit 15:14 MODOUT<1:0>: Modulator Output Setting for MDAT pins
   11 = Both CH0 and CH1 modulator outputs are present on MDAT1 and MDAT0 pins, both SINC fil- ters are off, no data ready pulse is present
   10 = CH1 ADC Modulator output present on MDAT1 pin, SINC filter on channel 1 is off, data ready pulse from channel 1 is not present on DR pin
   01 = CH0 ADC Modulator output present on MDAT0 pin, SINC filter on channel 0 is off, data ready pulse from channel 0 is not present on DR pin
   *00 = No Modulator output is enabled, SINC filters are on, data readys are present on DR pin for both channels (DEFAULT)
   
   bit 13  Unimplemented, read as 0
   
   bit 12  DR_HIZ: Data Ready Pin Inactive State Control
   *1 = The DR pin state is a logic high when data is NOT ready
   0 = The DR pin state is high impedance when data is NOT ready(DEFAULT)
   
   bit 11:10 DRMODE<1:0>: Data Ready Pin (DR) mode configuration bits
   11 = Both Data Ready pulses from CH0 and CH1 are output on DR pin
   10 = Data Ready pulses from CH1 ADC are output on DR pin. Data ready pulses from CH0 are not present on the DR pin.
   01 = Data Ready pulses from CH0 ADC are output on DR pin. Data ready pulses from CH1 are not present on the DR pin.
   *00 = Data Ready pulses from the lagging ADC between the two are output on DR pin. The lagging ADC depends on the PHASE register and on the OSR. (DEFAULT) 
   
   bit 9:8 DRSTATUS<1:0>: Data Ready Status
   *11 = ADC Channel 1 and Channel 0 data not ready (DEFAULT)
   10 = ADC Channel 1 data not ready, ADC Channel 0 data ready 
   01 = ADC Channel 0 data not ready, ADC Channel 1 data ready 
   00 = ADC Channel 1 and Channel 0 data ready
   */

  Write_MCP3911_Register (0x0A, B00010011); // data byte #1;

  /*
   bit 7:6 READ<1:0>: Address Loop Setting
   *11 = Address counter incremented, cycle through entire register set 
   10 = Address counter loops on register types (DEFAULT)
   01 = Address counter loops on register groups
   00 = Address not incremented, continually read single register
   
   bit 5: WRITE: Address Loop Setting for Write mode
   *1 = Address counter loops on entire register map (DEFAULT)
   0 = Address not incremented, continually write same single register
   
   bit 4:3 WIDTH <1:0> ADC Channel output data word width
   *11 = Both channels are in 24-bit mode(DEFAULT)
   10 = Channel1 in 24-bit mode, Channel0 in 16-bit mode
   01 = Channel1 in 16-bit mode, Channel0 in 24-bit mode 
   00 = Both channels are in 16-bit mode
   
   bit 2: EN_OFFCAL Enables or disables the 24-bit digital offset calibration on both channels 
   1 = Enabled; this mode does not add any group delay
   *0 = Disabled (DEFAULT)
   
   bit 1: EN_GAINCAL Enables or disables the 24-bit digital offset calibration on both channels
   1 = Enabled; this mode adds a group delay on both channels of 24 DMCLK periods. All data ready pulses are delayed by 24 clock periods compared to the mode with EN_GAINCAL=0 
   *0 = Disabled(DEFAULT)
   
   bit 0: Unimplemented, read as 0
   */

  Write_MCP3911_Register (0x0B, B11100000); 

  /* Offset Correction Register - Channel 0 i.e. Voltage (Read / Write)
   Address: 0x0E - 24 bits 
   
   bit 23:0 Digital Offset calibration value for the corresponding channel CHn. 
   This register simply is added to the output code of the channel bit-by-bit. This register is 24-bit two's complement MSB first coding. 
   CHn Output Code = OFFCAL_CHn + ADC CHn Output Code. 
   This register is a Don't Care if EN_OFFCAL=0 (Offset calibration disabled) but its value is not cleared by the EN_OFFCAL bit.
   
   Write_MCP3911_Register (0x0E, B00000000);
   Write_MCP3911_Register (0x0F, B00000000);
   Write_MCP3911_Register (0x10, B00000000);
   
   not implemented now, so disabled
   */

  /* Gain Correction Register - Channel 0 i.e. Voltage (Read / Write)
   Address: 0x11 - 24 bits 
   bit 23:0 Digital gain error calibration value for the corresponding channel CHn. 
   This register is 24-bit signed MSB first coding with a range of -1x to +0.9999999x (from 0x80000 to 0x7FFFFF). 
   The gain calibration adds 1x to this register and multiplies it to the output code of the channel bit by bit, after offset calibration. 
   The range of the gain calibration is thus from 0x to 1.9999999x (from 0x80000 to 0x7FFFFF). The LSB corresponds to a 2-23 increment in the multiplier.
   CHn Output Code = (GAINCAL_CHn+1)*ADC CHn Output Code. 
   This register is a Don't Care if EN_GAINCAL=0 (Offset calibration disabled) but its value is not cleared by the EN_GAINCAL bit.
   
   Write_MCP3911_Register (0x11, B00000000);
   Write_MCP3911_Register (0x12, B00000000);
   Write_MCP3911_Register (0x13, B00000000);
   
   not implemented now, so disabled
   */

  /* Offset Correction Register - Channel 1 i.e. Current (Read / Write)
   Address: 0x14 - 24 bits 
   This register simply is added to the output code of the channel bit-by-bit. This register is 24-bit two's complement MSB first coding. 
   CHn Output Code = OFFCAL_CHn + ADC CHn Output Code. 
   This register is a Don't Care if EN_OFFCAL=0 (Offset calibration disabled) but its value is not cleared by the EN_OFFCAL bit.
   
   Write_MCP3911_Register (0x14, B00000000);
   Write_MCP3911_Register (0x15, B00000000);
   Write_MCP3911_Register (0x16, B00000000);
   
   not implemented now, so disabled
   */

  /* Gain Correction Register - Channel 1  i.e. Current (Read / Write)
   Address: 0x17 - 24 bits 
   
   bit 23:0 Digital gain error calibration value for the corresponding channel CHn. 
   This register is 24-bit signed MSB first coding with a range of -1x to +0.9999999x (from 0x80000 to 0x7FFFFF). 
   The gain calibration adds 1x to this register and multiplies it to the output code of the channel bit by bit, after offset calibration. 
   The range of the gain calibration is thus from 0x to 1.9999999x (from 0x80000 to 0x7FFFFF). The LSB corresponds to a 2-23 increment in the multiplier.
   CHn Output Code = (GAINCAL_CHn+1)*ADC CHn Output Code. 
   This register is a Don't Care if EN_GAINCAL=0 (Offset calibration disabled) but its value is not cleared by the EN_GAINCAL bit.
   
   Write_MCP3911_Register (0x17, B00000000);
   Write_MCP3911_Register (0x18, B00000000);
   Write_MCP3911_Register (0x19, B00000000);
   
   not implemented now, so disabled
   */

  /*Internal Voltage reference Temperature Coefficient Adjustment (Read / Write) 
   Address: 0x1A - 8 bits 
   bit 7:0 Internal Voltage Temperature coefficient register value. (See compensation (VREFCAL register)” for complete description). Section 5.7.3
   
   Write_MCP3911_Register (0x1A, 0x42);
   
   not implemented now, so disabled
   */

  /* R/W Configuration Register (Read / Write)
   Address: 0x0C - 16 bits   
   bit 15:14 PRE<1:0> Analog Master Clock (AMCLK) Prescaler Value 
   11 = AMCLK = MCLK / 8
   10 = AMCLK = MCLK / 4
   01 = AMCLK = MCLK / 2
   *00 = AMCLK = MCLK (DEFAULT)
   
   bit 13:11 OSR<2:0> Oversampling Ratio for Delta-Sigma A/D Conversion (ALL CHANNELS, fd / fS) 
   111=4096(fd=244spsforMCLK=4MHz, fs=AMCLK=1MHz) 
   *110=2048(fd=488spsforMCLK=4MHz, fs=AMCLK=1MHz)
   101=1024(fd=976spsforMCLK=4MHz, fs=AMCLK=1MHz) 
   100=512(fd=1.953kspsforMCLK=4MHz, fs=AMCLK=1MHz)
   011 = 256 (fd = 3.90625 ksps for MCLK = 4 MHz, fs = AMCLK = 1 MHz) (DEFAULT) 
   010=128(fd=7.8125kspsforMCLK=4MHz, fs=AMCLK=1MHz) 
   001=64(fd=15.625kspsforMCLK=4MHz, fs=AMCLK=1MHz) 
   000=32(fd=31.25kspsforMCLK=4MHz, fs=AMCLK=1MHz)
   
   bit 10:9 DITHER<1:0> Control for dithering circuit for idle tones cancellation and improved THD
   11 =DitheringON,bothchannels,Strength=Maximum(MCP3901Equivalent)-(DEFAULT)
   10 = Dithering ON, both channels, Strength = Medium 
   *01 =DitheringON,bothchannels,Strength=Minimum 
   00 = Dithering turned OFF
   
   bit 8 AZ_FREQ Auto-zero frequency setting
   1 = Auto-zeroing algorithm running at higher speed
   *0 = Auto-zeroing algorithm running at lower speed (Default)
   */

  Write_MCP3911_Register (0x0C, B00110010);

  /*
   bit 7:6 RESET<1:0>: Reset mode setting for ADCs
   11 = Both CH0 and CH1 ADC are in reset mode 
   10 = CH1 ADC in reset mode
   01 = CH0 ADC in reset mode
   *00 = Neither ADC in reset mode(default)
   
   bit5:4 SHUTDOWN<1:0>: Shutdown mode setting for ADCs
   11 = Both CH0 and CH1 ADC in Shutdown 
   10 = CH1 ADC in Shutdown
   01 = CH0 ADC in Shutdown
   *00 = Neither Channel in Shutdown(default)
   
   bit 3: Not implemented, read as 0
   
   bit 2: VREFEXT Internal Voltage Reference Shutdown Control 
   1 = Internal Voltage Reference Disabled
   *0 = Internal Voltage Reference Enabled (Default)
   
   bit 1: CLKEXT Internal Clock selection bits
   *1 = External clock drive by MCU on OSC1 pin (crystal oscillator disabled, no internal power consumption) (Default)
   0 = Crystal oscillator is enabled. A crystal must be placed between OSC1 and OSC2 pins.
   
   bit 0: Not implemented, read as 0
   */

  Write_MCP3911_Register (0x0D, B00000010); 

  Serial.println("MCP3911 Init complete...");
}

uint8_t Write_MCP3911_Register (uint8_t MCP3911_Register_Address, uint8_t Command) {
  Serial.print("Command Register Received: ");
  Serial.print(MCP3911_Register_Address,BIN);
  Serial.print(" - Command Received: ");
  Serial.println(Command,BIN);

  MCP3911_Register_Address <<= 1;   //left shift address one digit
  digitalWrite(MCP3911_CS, LOW); // now take CS low to enable SPI device
  SPI.transfer(MCP3911_Register_Address); // send address with write command to MCP3911
  SPI.transfer(Command); //now send payload
  digitalWrite(MCP3911_CS, HIGH); // deselect the CS pin. 

  Serial.print(" Write Command Byte Sent: ");
  Serial.println(MCP3911_Register_Address,BIN); // verify what command was sent (i.e. address and write bit = 0)

  //Now Verify all went well. If so, have the function return value of one,
  //otherwise, alert the user that something is amiss. 
  uint8_t Response = Read_MCP3911_Register (MCP3911_Register_Address>>1);
  if (Response == Command)  return 1;
  else 
  {
    Serial.println("");
    Serial.print("Error for register: ");
    Serial.print(MCP3911_Register_Address>>1,BIN);
    Serial.print(" - Command Sent: ");
    Serial.print(Command,BIN);
    Serial.print(" - Response Received: ");
    Serial.println(Response,BIN);
    Serial.println("");
    return 0;
  }
}

uint8_t Read_MCP3911_Register (uint8_t MCP3911_Register_Address) {

  MCP3911_Register_Address <<=1; //left shift address one bit for command byte 
  MCP3911_Register_Address |=1; // Ensure read bit is set

  //Serial.print("  Read Byte Command Sent: ");
  //Serial.print(MCP3911_Register_Address,BIN);

  digitalWrite(MCP3911_CS, LOW); 
  SPI.transfer(MCP3911_Register_Address); // send address with read command to MCP3911
  uint8_t Response = SPI.transfer(0x0); 
  digitalWrite(MCP3911_CS, HIGH);

  //Serial.print(" - Response Received: ");
  //Serial.println(Response,BIN);
  return Response;
}
 
You can NOT get a square wave output with this:

Code:
  analogWriteResolution(1);//make it single-bit only (need a SQW)

One bit of resolution means the only 2 possible outputs are always HIGH or always LOW.

Set the resolution to 8 bits. Even though the hardware isn't capable of 8 bits, the software in analogWrite() will scale your numbers to the available range the hardware has at that PWM frequency. Values like 127 or 128 should give you the square wave you want, if the hardware is capable of producing it.
 
Apologies!

Just goes to show how I misunderstood the documentation. I will heed your advice. For whatever reason, I thought that the number in the analogWriteResolution command referred to the bits that could be used to represent a waveform / shape. Hence my incorrect assumption that a single-bit value would result in a square wave. Now I understand that the PWM waves are always square and that your handy resolution tool simply expanded the available universe of acceptable frequencies. Just goes to show how easily I missed the details.

Anyhow, I will re-write the program and go from there. Thank you again for your help. Constantin
 
Last edited:
Well, FWIW, even if I set the analogWriteResolution to 8 and use 128 for AnalogWrite, I get nothing in setup now. I have no idea why and it doesn't really matter. I'll simply set it up once in loop and forget about it.
 
Status
Not open for further replies.
Back
Top