Something is off with my timing

Hello,

I am trying to create a temperature probe using an LMT01 and an ATmega328P.
I have attached a schematic of my circuit.
Here is the code I am running.

volatile int pulseCount = 0;
int pulseTotal = 0;

void setup()
{
  Serial.begin(9600);
  ACSR = B01011010;    //Setup the Analog Comparator Register.
}

void loop()
{
  if (pulseCount != 0)
  {
    while (pulseCount != pulseTotal)
    {
      pulseTotal = pulseCount;
      delay(1);
    }
    float tCelsius = pulseCount * 0.0625 - 50;
    Serial.print(tCelsius);
    Serial.println("°C");
    float tFahrenheit = tCelsius * 1.8 + 32;
    Serial.print(tFahrenheit);
    Serial.println("°F");
    pulseCount = 0;
  }
  delay(2);
}

//Interrupt Service Routine, counts pulses
ISR(ANALOG_COMP_vect)
{
  pulseCount += 1;
}

Since I am using the internal OSC, I have the following boards.txt

3288.name=My 328P 8MHz
3288.upload.tool=arduino:avrdude
3288.upload.maximum_size=32768
328.upload.maximum_data_size=2048

3288.bootloader.tool=avrdude
3288.bootloader.low_fuses=0xE2
3288.bootloader.high_fuses=0xD1
3288.bootloader.extended_fuses=0xFD
3288.bootloader.unlock_bits=0x3F
3288.bootloader.lock_bits=0x2F

3288.build.mcu=atmega328p
3288.build.f_cpu=8000000L
3288.build.board=My_328P_8MHz
3288.build.core=arduino:arduino
3288.build.variant=arduino:standard

I have fused the chip as follows:

avrdude -c usbasp -p m328p -U lfuse:w:0xe2:m
avrdude -c usbasp -p m328p -U hfuse:w:0xd9:m
avrdude -c usbasp -p m328p -U efuse:w:0x07:m

When looking at the serial output on an oscilliscope, the timing is way off 9600 baud.

I need it to be 9600 so attached equipment can read the data. What am I missing?

Temp Probe Schematic.pdf (16.8 KB)

What am I missing?

I don’t know why the timing is off, but I can offer a suggestion. The MiniCore core will allow you to painlessly bootload the Mega328P (and Mega328) to run at 8MHz without changing any boards file and sets the fuses automatically. Also, with MiniCore you get to use the oscillator pins as GPIO (as pins 20 and 21).

Thank you. I tried out MiniCore and the 8MHz option. I had no success with it, but it reminded me of advice that I might give another. I need to get "Hello, World." working at 9600 baud with the 8MHz oscillator before I go into the deep end with the analog comparator, internal reference voltage and interrupt service routines.

I had no success with it,

I have had no problems using MiniCore other than, you must make sure to pick the right variant of 328 (328 or 328P). And that is just me not paying attention to the processor type, not a problem with the core.

For anyone following this thread, or that has interest in a temperature sensor project, I wanted to post an update... My problem had nothing to do with my boards.txt or fuses. Both are correct. Doing it as I am, I can use Arduino Core for 100% compatibility.

The problem was in that my LMT01 was connected to A1 as per Texas Instrument's example code and reference schematic, which is flawed.

To use one of the analog pins, more of the registers in the ATMega328P need to be configured than just the ACSR.

But, if I move the LMT01 (and 13.3 Kohm resistor) to connect to pin 7 (PD7 or AIN1) it works on the example code and nothing further is needed.

In case anyone wanted to look at a picture.

If I may make a couple of suggestions. There should be 0.1uf bypass caps from Vcc and Avcc to ground as close to the 328 chip as possible and Aref should not be directly connected to Avcc. Bypass Aref to ground with a 0.1uf cap.

groundFungus:
If I may make a couple of suggestions. There should be 0.1uf bypass caps from Vcc and Avcc to ground as close to the 328 chip as possible and Aref should not be directly connected to Avcc. Bypass Aref to ground with a 0.1uf cap.

Thank you for the suggestions. They follow the same advice from the specification sheet and application notes. If I were using the ADC to measure an analog signal, I would follow your advice to eliminate noise with a smaller current loop. There are other measures I could take to stabilize AVCC and AREF, like a ferrite choke, if necessary. The LMT01 pulses current between a low and a high, which R2 converts to a voltage, essentially a digital signal, not analog. I can save a few parts and therefore money if I tie things contrary to recommended advice. In my application, the additional parts would have no positive effect.

In order to smooth out the temperature fluctuation, I want to average the most recent 256 samples together and output the value in Celsius, formated as sign, 3-digit integer, decimal, 10ths and C… e.g. +025.1C

In order to get the formatting correct, and to test all possible values, I wrote the following code which works flawlessly.

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  for (int index = 1; index <= 4095; index++)
  {
    float tCelsius = index * 0.0625 - 50;
    float tAbsoluteValue = abs(tCelsius);
    if (tCelsius >= 0.0)
    {
      Serial.print ("+");
    }
    else if (tCelsius < 0.0)
    {
      Serial.print ("-");
    }
    if (tAbsoluteValue < 100.0)
    {
      Serial.print("0");
    }
    if (tAbsoluteValue < 10.0)
    {
      Serial.print("0");
    }
    Serial.print(tAbsoluteValue, 1);
    Serial.println("C");
    delay (100);
  }
}

However, taking portions of that code and adding it to my LMT01 program to operate on actual temperature values, I once again see nothing coming out of the serial port. I am sure it’s a simple mistake, but I can’t figure it out.

Here is the code that I need to fix.

volatile int pulseCount = 0;// stores the pulses from the LMT01; updates as an interrupt (hence "volatile")
int pulseHold = 0;// stores a current value for pulseCount; updates with each loop
byte index = 0;// indexes tCelsius; continuously rolls over, 0-255
int pulseTotals[257];// stores the most recent 256 values from LMT01, approximately the most recent 26.6 seconds
unsigned long serialTimestamp = 0;//stores the moment in microseconds when the serial is sent.

void setup()
{
  Serial.begin(9600);
  ACSR = B01011010;    //Setup the Analog Comparator Register
}

void loop()
{
  if (pulseCount != 0)
  {
    while (pulseCount != pulseHold)
    {
      pulseHold = pulseCount;
      delay(1);
    }
    pulseTotals[index] = pulseCount;
    pulseCount = 0;
    index++;
  }
  delay(2);
  long total = 0;
  for (byte tIndex = 0; tIndex <= 255; tIndex++)
  {
    total += pulseTotals[tIndex];
  }
  float average = total / 256;
  float tCelsius = average * 0.0625 - 50;
  float tAbsoluteValue = abs(tCelsius);
  if (tCelsius >= 0.0)
  {
    Serial.print ("+");
  }
  else if (tCelsius < 0.0)
  {
    Serial.print ("-");
  }
  if (tAbsoluteValue < 100.0)
  {
    Serial.print("0");
  }
  if (tAbsoluteValue < 10.0)
  {
    Serial.print("0");
  }
  Serial.print(tAbsoluteValue, 1);
  Serial.println("C");
}

//Interrupt Service Routine, counts pulses
ISR(ANALOG_COMP_vect)
{
  pulseCount += 1;
}
for (byte tIndex = 0; tIndex <= 255; tIndex++)

Here’s my problem…

a byte only contains 0-255. My check is out of range of my index.

I get hung up on the most elementary things.