Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 10 of 10

Thread: LM324 op-amp output to Teensy 3.2 analog input reads 0.00. Meter shows 2.96v. Help?

  1. #1
    Junior Member
    Join Date
    Sep 2020
    Posts
    1

    LM324 op-amp output to Teensy 3.2 analog input reads 0.00. Meter shows 2.96v. Help?

    Hello. I just started using Teensy a few days ago to allow me to use the FreqMeasure library to check the clock frequency of a processor on a board under test. The main brain in the fixture is an Arduino Mega 2560 v3, but a) I'm already using every single pin it has, and b) it's not fast enough to measure the frequency (16Khz or 32Khz, depending on the mode) and still get everything else done. I got FreqMeasure and I2C communication between the Mega and the Teensy working pretty easily. But then I realized I needed to measure a 3.3V and -3.3V supply, and thought, "Hey - I can just use the analog inputs on the Teensy and request the values via I2C like I'm doing with the frequency!". But for some reason, while the 3.3v reads fine on A7, I'm getting 0.00 on A8, which is connected to the output of a unity gain inverting LM324 that gives me 2.96V on a meter when fed -2.96V. I've tried swapping pins around, inserting delays, etc, but nothing works. Any suggestions? I realize I need to add some code to reply to requests for the voltage, etc, but I need to *get* it first! Any help would be appreciated. Impendance issue, maybe?

    -Bill

    Code:
    #include <Wire.h>
    #include <FreqMeasure.h>
    
    
    byte SlaveReceived = 0;
    int frequency;
    double sum = 0;
    int count = 0;
    int maxWait = 10000; //max # of ms to wait for a reading before returning 0
    
    float v33; //+3.3v from CBA
    float n33; //-3.3v from CBA
    
    void setup() {
      //Serial.begin(57600);
      Wire.begin(8);
      FreqMeasure.begin();
      //Wire.onReceive(receiveEvent);           //Function call when Slave receives value from master
      Wire.onRequest(requestEvent);           //Function call when Master request value from Slave
    
    }
    
    void loop() {
     
      v33 =(analogRead(A8) / 1023 * 3.3);
      //delay(500);
      n33 = (analogRead(A9) / 1023 * 3.3); //-3.3v inverted via LM324 to +3.3v
      //delay(500);
      Serial.println("v33=" + String(v33));
      Serial.println("n33=" + String(n33));
    
      if (FreqMeasure.available()) {
        // average several readings together
        sum = sum + FreqMeasure.read();
        count = count + 1;
        if (count > 30) {
          frequency = FreqMeasure.countToFrequency(sum / count);
          Serial.println("[" + String(frequency) + "]");
          sum = 0;
          count = 0;
        }
      }
    }
    
    void requestEvent(void)                                //called when master wants value from slave
    {
      //  int start = millis();
      //  frequency = 0;
      //  do {
      //
      //  }
      //} while ((frequency == 0) && (millis() < (start + maxWait)));
      byte msb = highByte(frequency);
      byte lsb = lowByte(frequency);
      //  Serial.print("[" + String(frequency) + "]");
      //  Serial.println("Sending: " + String(msb) + " " + String(lsb));
      Wire.write(msb);                          // sends one byte
      Wire.write(lsb);
    
    }
    Click image for larger version. 

Name:	Capture.PNG 
Views:	43 
Size:	30.6 KB 
ID:	21569

  2. #2
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    626
    > v33 =(analogRead(A8) / 1023 * 3.3);

    I don't know why there is a difference between pins, but add a decimal to 1023 to make it use floating point.

  3. #3
    Quote Originally Posted by jonr View Post
    > v33 =(analogRead(A8) / 1023 * 3.3);

    I don't know why there is a difference between pins, but add a decimal to 1023 to make it use floating point.
    If you write that as: v33 =(analogRead(A8) * (3.3 / 1023.0));

    You get the same result but let the compiler combine the constants saving a floating point op at run time.

    I would be very careful with that inverter circuit. The common mode input voltage is outside the specified range of the LM324. (The inverting input will be at -Vout/gain.) The input range of some opamps does go slightly below their lower voltage rail but the LM324 is not one of them. Or at least not in the data sheet I looked at.

  4. #4
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    626
    > saving a floating point op at run time

    You can also leave the expression in the same order and specify the gcc option "-ffast-math".

  5. #5
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    626
    Did I miss something (using a TI data sheet)? I don't see a problem with the LM324 - even if Vin exceeds the expected -3.3V to 0V range (except for over voltage to the ADC input).

  6. #6
    Senior Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    117
    the lm324 has restricted input voltage common mode range - 1.7 v from +supply and
    0v from -supply so if it is powered from 5v the inputs can go as high as 3.3 with no
    tolerance and no margin. the output swing is also limited. with 5v supply output swing
    high is 3.5 typ 3.3 min and output swing low is 5 mv typ 20 mv min even with a 10k rl
    from out to gnd. also, if the input common mode voltage range is exceeded (depending
    on where the other input is) the output can lock high (ie 1.5-1.7 volt from +supply) -
    this is sometimes referred to as phase inversion.

    all in all not the best choice to drive a teensy adc input - much better to use a cmos
    rail to rail in and rail to rail out amplifier in a non-inverting gain of 1 in this application.
    for example the TLV2370 available from Digikey. there are dozens and dozens of
    amplifiers like this available.

  7. #7
    I am reminded of an old DATAQ DI-194 data acquisition system I have. It used an ADC with a 0-5V input range but had a resistor input network that let it measure -10 to +10V.

  8. #8
    Senior Member
    Join Date
    Aug 2019
    Location
    southwest USA
    Posts
    117
    had overlooked on the schematic -non inverting input of lm324 at ground - will not work as desired that way.
    non inverting input would have to be at 1.65 or so volts for proper action.

    edit - is that a minus sign on the 3.3 v input to the amp? if so a gnd connection for the non inverting input
    would be ok -3.3 in would be 3.3 out but -3.4 in would be 3.4 out and that is beyond the worst case spec
    for the 324 so maybe you would want to decrease the feedback resistor a little to give yourself some margin
    and calculate that out after you make the measurement.
    Last edited by analog&RFmodels; 09-03-2020 at 12:43 AM.

  9. #9
    Senior Member Jp3141's Avatar
    Join Date
    Nov 2012
    Posts
    486
    You don't really need an opamp.

    If you don't need perfect accuracy, connect 2 resistors in series between the +3.3 V and -3.3 V line that you want to measure. Connect the junction to the ADC input. Make the R to the +3.3 V slightly lower in resistance than the other one -- say 10k to +3.3 V (call it R1), and the other one 15k (call it R2). Now the voltage at the junction is:
    Vmid = (VHIGH*15k+VLOW*10k)/25k. Measure VHIGH first (as you are doing -- but if the +3.3 V is above the Teensy's '3.3V', the ADC will saturate at 1023), and then measure VMID and calculate the VLOW value.

    Your largest error will be the resistors tolerance -- maybe you can get to within a few %, or calibrate it if you need more accuracy. You would have nearly the same error in the opamp anyway -- its gain of '-1' depends on 2 resistors too.

  10. #10
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    626
    Don't use high input impedance. As I recall, the manual suggests < 4K ohms.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •