ADC problem with 3.xx

Status
Not open for further replies.

2n3055

Well-known member
Hi,

this example is used:
Code:
/*
  Copyright (c) 2014-2015 NicoHood
  See the readme for credit to other people.

  MSGEQ7 Serial example
  Output via Serial

  Needs no special hardware and displays raw values on the Serial monitor.

  Reads MSGEQ7 IC with 7 different frequencys from range 0-255
  63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25KHz, 16kHz
*/

// MSGEQ7
#include "MSGEQ7.h"
#define pinAnalogLeft A0
#define pinAnalogRight A9
#define pinReset 3
#define pinStrobe 2

#define MSGEQ7_INTERVAL ReadsPerSecond(50)
#define MSGEQ7_SMOOTH false

CMSGEQ7<MSGEQ7_SMOOTH, pinReset, pinStrobe, pinAnalogLeft, pinAnalogRight> MSGEQ7;

void setup() {
  analogReference(INTERNAL);
  // This will set the IC ready for reading
  MSGEQ7.begin();
  pinMode(A9, INPUT);
  pinMode(A8, INPUT);
    pinMode(pinReset, OUTPUT);
  pinMode(pinStrobe, OUTPUT);
  
  // Serial setup with faster baud rate gives more FPS (115200)
  Serial.begin(115200);
  Serial.println(F("Startup"));
}

void loop() {
  // Analyze without delay every interval
  bool newReading = MSGEQ7.read(MSGEQ7_INTERVAL);

  // Calculate FPS
  uint16_t FPS = getFPS(newReading);

  // Serial raw debug output
  if (newReading)
    serialBars(FPS);
}

void serialBars(uint16_t FPS) {
  // Visualize the average bass of both channels
  uint8_t input = MSGEQ7.get(MSGEQ7_BASS);

  // Reduce noise
  input = mapNoise(input);

  // Save the difference between the last beat
  static uint8_t lastInput = 0;
  int delta = input - lastInput;
  lastInput = input;

  // All channels together
  Serial.print(input);
  Serial.print(F(" In\t"));

  // Difference between last measurement
  Serial.print(delta);
  Serial.print(F(" D\t"));

  // 1st channel (here: left)
  Serial.print(MSGEQ7.get(MSGEQ7_BASS, 0));
  Serial.print(F(" R\t"));

  // 2nd channel (here: left)
  Serial.print(MSGEQ7.get(MSGEQ7_BASS, 1));
  Serial.print(F(" L\t"));

  // overall volume of all channels
  Serial.print(MSGEQ7.getVolume());
  Serial.print(F(" Vol\t"));

  // FPS of the reading
  Serial.print(FPS);
  Serial.print(F(" FPS \t"));

  // Highlight high pitches
  char c = '=';
  if (delta >= 20)
    c = '#';

  // Visualize with characters as bars
  for (uint8_t i = 0; i < (input / 4); i++)
  {
    if (i == 192 / 4 - 1)
      Serial.print('+');
    else if (i == 128 / 4 - 1)
      Serial.print('*');
    else if (i == 64 / 4 - 1)
      Serial.print('X');
    else
      Serial.print(c);
  }
  Serial.println();
}

uint16_t getFPS(bool newReading) {
  // Variables to count FPS and last 1 second mark
  static uint16_t prevFPS = 0;
  static uint16_t FPS = 0;
  static uint32_t m = 0;

  // Increase FPS count
  if (newReading)
    FPS++;

  // If 1 second mark crossed, save new FPS
  if ((micros() - m) > 1000000) {
    prevFPS = FPS;
    FPS = 0;
    m = micros();
  }

  return prevFPS;
}

It works fine with Teensy2 but not with 3.6.
What is it wrong ????
Thanks
 
maybe attach a photo of how things are wired together .... T3.6 is NOT 5v tolerant, so you need to power MSGEQ7 with 3.3v
 
A speed problem, maybe. Teensy 3.6 is way faster. Perhaps try 16 MHz Setting? If that works, the library needs some additonal delays. Just a guess.
 
As FrankB notes, likely a "speed problem". T3.6 is 10 times faster then Teensy 2. MSGEQ7 data sheet has minimum times for reset and probe pulses. you may need to add some delayMicroseconds(n); between digtalWrite's to the library where it does reset and probe.

https://www.sparkfun.com/datasheets/Components/General/MSGEQ7.pdf

https://www.eetimes.com/author.asp?section_id=216&doc_id=1323030

EDIT: I don't have the MSGEQ7 IC, but with analyzer i can measure reset and strobe pulses when running Serial example. Here is what i see on Teensy 2 and T3.6 vs the minimum spec from the data sheet

Code:
         at 50 fps, reset interval is 20 ms    (min is from spec)
        min      T2         T3.6   (us)
tr        0.1     0.125      0.175
trs      72       0.575      0.15
ts hi    18       0.425      0.175
ts lo    54?    148         50
tss      72     148         50
to       36
Some timings are out of spec, even for the Teensy 2. Looks like to be in spec, you need to add some delayMicroseconds()
 
Last edited:
Hello Manitou,

Thanks for you study with the logic analyser.

I added some time to respect the datasheet without success. I tried to add some longer timing as you measured with your analyser without success.
I'd really appreciated if you could test it with the new values ?

In advance thanks a lot.
Code:
/*
Copyright (c) 2014-2015 NicoHood
See the readme for credit to other people.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

// include guard
#pragma once


//================================================================================
// Tools
//================================================================================

MSGEQ7_data_t mapNoise(MSGEQ7_data_t x, MSGEQ7_data_t in_min, MSGEQ7_data_t in_max, MSGEQ7_data_t out_min, MSGEQ7_data_t out_max)
{
	// if input is smaller/bigger than expected return the min/max out ranges value
	if (x < in_min)
		return out_min;
	else if (x > in_max)
		return out_max;

	// map the input to the output range.
	// round up if mapping bigger ranges to smaller ranges
	else  if ((in_max - in_min) > (out_max - out_min))
		return (uint16_t)(x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min;
	// round down if mapping smaller ranges to bigger ranges
	else
		return (uint16_t)(x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}


//================================================================================
// MSGEQ7
//================================================================================

// initialize the instance's variables
template <uint8_t smooth, uint8_t resetPin, uint8_t strobePin, uint8_t firstAnalogPin, uint8_t ...analogPins>
CMSGEQ7<smooth, resetPin, strobePin, firstAnalogPin, analogPins ...>::
CMSGEQ7(void)
{
	// empty
}


//================================================================================
// IC setup
//================================================================================

template <uint8_t smooth, uint8_t resetPin, uint8_t strobePin, uint8_t firstAnalogPin, uint8_t ...analogPins>
void CMSGEQ7<smooth, resetPin, strobePin, firstAnalogPin, analogPins ...>::
begin(void){
	// do whatever is required to initialize the IC
	pinMode(resetPin, OUTPUT);
	pinMode(strobePin, OUTPUT);
	pinMode(firstAnalogPin, INPUT);
	nop((pinMode(analogPins, INPUT), 0)...);
}

template <uint8_t smooth, uint8_t resetPin, uint8_t strobePin, uint8_t firstAnalogPin, uint8_t ...analogPins>
void CMSGEQ7<smooth, resetPin, strobePin, firstAnalogPin, analogPins ...>::
end(void){
	// set pins to input again to safely remove connections if needed
	pinMode(resetPin, INPUT);
	pinMode(strobePin, INPUT);
	pinMode(firstAnalogPin, INPUT);
	nop((pinMode(analogPins, INPUT), 0)...);
}

template <uint8_t smooth, uint8_t resetPin, uint8_t strobePin, uint8_t firstAnalogPin, uint8_t ...analogPins>
void CMSGEQ7<smooth, resetPin, strobePin, firstAnalogPin, analogPins ...>::
reset(void){
	// only this setting seems to works properly
	digitalWrite(strobePin, LOW);
	digitalWrite(resetPin, HIGH);
[B]delayMicroseconds(1); [/B] //added for Teensy 3
	digitalWrite(resetPin, LOW);
[B]delayMicroseconds(75); [/B]//added for Teensy 3
}


//================================================================================
// read
//================================================================================

template <uint8_t smooth, uint8_t resetPin, uint8_t strobePin, uint8_t firstAnalogPin, uint8_t ...analogPins>
bool CMSGEQ7<smooth, resetPin, strobePin, firstAnalogPin, analogPins ...>::
read(void){
	// reset the IC frequently, otherwise it will get out of sync after a while
	reset();

	// read all 7 channels
	// 63Hz, 160Hz, 400Hz, 1kHz, 2.5kHz, 6.25KHz, 16kHz
	for (uint8_t i = 0; i < 7; i++){
		// trigger next value
		digitalWrite(strobePin, HIGH);
[B]delayMicroseconds(36); //adjusted for Teensy 3[/B]
		digitalWrite(strobePin, LOW);

		// allow the output to settle
		[B]delayMicroseconds(114); //adjusted for Teensy 3 to be sure to get the 150 measured [/B]

		// read pins with 8 bit resolution
		frequency f = (frequency){
#ifdef MSGEQ7_10BIT
			analogRead(firstAnalogPin),
				analogRead(analogPins)...
#else
			MSGEQ7_data_t(analogRead(firstAnalogPin) >> 2),
				MSGEQ7_data_t(analogRead(analogPins) >> 2)...
#endif
		};

		// Save smooth values
		if (smooth){
			for (uint8_t p = 0; p < (1 + sizeof...(analogPins)); p++){
				// Round up if value increases
				if (frequencies[i].pin[p] < f.pin[p])
					frequencies[i].pin[p]++;

				// Smooth value
				frequencies[i].pin[p] = uint16_t(frequencies[i].pin[p] * smooth + f.pin[p] * (255 - smooth)) / 255;
			}
		}
		// Save peek values
		else
			frequencies[i] = f;

	}
	return true;
}

template <uint8_t smooth, uint8_t resetPin, uint8_t strobePin, uint8_t firstAnalogPin, uint8_t ...analogPins>
bool CMSGEQ7<smooth, resetPin, strobePin, firstAnalogPin, analogPins ...>::
read(const uint32_t interval){
	// Read without delay
	// TODO use static variable??
	static uint32_t prevMicros = 0;
	uint32_t currentMicros = micros();
	if ((currentMicros - prevMicros) > interval) {
		prevMicros = currentMicros;

		// Analyze
		read();
		return true;
	}
	return false;
}


//================================================================================
// get values
//================================================================================

template <uint8_t smooth, uint8_t resetPin, uint8_t strobePin, uint8_t firstAnalogPin, uint8_t ...analogPins>
MSGEQ7_data_t CMSGEQ7<smooth, resetPin, strobePin, firstAnalogPin, analogPins ...>::
get(const uint8_t frequency, const uint8_t channel){
	// dont read out of bounds
	if (frequency >= 7 || channel >= (1 + sizeof...(analogPins)))
		return 0;

	// returns the last measurement
	return frequencies[frequency].pin[channel];
}

template <uint8_t smooth, uint8_t resetPin, uint8_t strobePin, uint8_t firstAnalogPin, uint8_t ...analogPins>
MSGEQ7_data_t CMSGEQ7<smooth, resetPin, strobePin, firstAnalogPin, analogPins ...>::
get(const uint8_t frequency){
	// dont read out of bounds
	if (frequency >= 7)
		return 0;

	// go through all channels/pins and add measured values
	uint16_t average = 0;
	for (uint8_t p = 0; p < (1 + sizeof...(analogPins)); p++)
		average += frequencies[frequency].pin[p];

	// return the average of all channels
	return (average / (1 + sizeof...(analogPins)));
}

template <uint8_t smooth, uint8_t resetPin, uint8_t strobePin, uint8_t firstAnalogPin, uint8_t ...analogPins>
MSGEQ7_data_t CMSGEQ7<smooth, resetPin, strobePin, firstAnalogPin, analogPins ...>::
getVolume(uint8_t channel){
	// dont read out of bounds
	if (channel >= (1 + sizeof...(analogPins)))
		return 0;

	// add all frequencies of a single channel to the overall volume
	uint16_t vol = 0;
	for (uint8_t i = 0; i < 7; i++)
		vol += frequencies[i].pin[channel];

	// return the average of this channels
	return vol / 7;
}

template <uint8_t smooth, uint8_t resetPin, uint8_t strobePin, uint8_t firstAnalogPin, uint8_t ...analogPins>
MSGEQ7_data_t CMSGEQ7<smooth, resetPin, strobePin, firstAnalogPin, analogPins ...>::
getVolume(void){
	// add all frequencies of all channels to the overall volume
	uint16_t vol = 0;
	for (uint8_t i = 0; i < 7; i++)
		vol += get(i);

	// return the average of all channels
	return vol / 7;
}
 
Your changes look appropriate, but since I don't have the chip, any testing I do will only be superficial. The true test are yours with the chip.

The only other thought is that the changes you make to the library are not being compiled into your sketch. As a sanity check, you could put a garbage line in a library file (or misspell delayMicroseconds) so the compiler will get an error and confirm the IDE is building with your modified copy of the library ...

a photo of your wiring with the T3.6 might reveal something.
 
Thanks for your inputs!
Tried the sanity check! I got an error if a mistake is inside the .hpp

Tried again with the Teensy 2 works perfectly. Using the same schematics and value as the datasheet !

Does it have some difference because it's a 32 bits and some reading could be wrong ?????

Thanks
 
It works fine with Teensy2 but not with 3.6.
What is it wrong ????
Thanks

What do you mean it doesn't work? Even with nothing connected to any of the pins, the T3.6 sketch prints stuff ...
Code:
...
81 In	-7 D	102 R	88 L	71 Vol	50 FPS 	===============X====
84 In	3 D	103 R	94 L	68 Vol	50 FPS 	===============X=====
74 In	-10 D	99 R	79 L	82 Vol	50 FPS 	===============X==
99 In	25 D	122 R	103 L	72 Vol	50 FPS 	###############X########
71 In	-28 D	90 R	82 L	76 Vol	50 FPS 	===============X=
83 In	12 D	101 R	93 L	74 Vol	50 FPS 	===============X====
97 In	14 D	120 R	100 L	77 Vol	50 FPS 	===============X========
...

if you just print analogRead(pin) for each analog pin A0/A9 in a loop on the T3.6 (with a delay(500)), you should get back random values with nothing connected to the analog pins. You could confirm the analog pins are OK, by jumpering GND to one of the analog pins, and the output should change to 0 or 1 for that pin. are the header pins of your T3.6 soldered? again, PLEASE attach a photo of your wiring ....
 
With 3 A/D displayed, nothing connected:

Code:
935 1023 1003
933 1023 876
933 1023 960
933 1023 897
933 1020 873
933 1008 833
935 986 888
934 1023 887
933 1021 875
934 909 817
934 974 879
934 1023 954
933 1023 885
934 1023 921
933 1023 947

With both at 0V:

Code:
1 1 2
2 1 3
2 1 4
3 5 3
1 4 3
2 3 3
4 2 3

With both at 3.3V
Code:
1023 1023 1023
1023 1023 1023
1023 1023 1023
1023 1023 1023
1023 1023 1023
1023 1023 1023
1023 1023 1023
1023 1023 1023
1023 1023 1023
1023 1023 1023
1023 1023 1023
1023 1023 1023

The schematic:
No cabling it's on a PCB, the routing is ok !
MSGEQ.jpeg

With or without signal (or signal to GND) (no chip installed on L channel!):
Code:
15 In	-3 D	68 R	0 L	38 Vol	50 FPS 	===
22 In	7 D	82 R	0 L	36 Vol	50 FPS 	=====
24 In	2 D	87 R	0 L	41 Vol	50 FPS 	======
32 In	8 D	100 R	0 L	39 Vol	50 FPS 	========
21 In	-11 D	80 R	0 L	41 Vol	50 FPS 	=====
18 In	-3 D	74 R	0 L	38 Vol	50 FPS 	====
32 In	14 D	100 R	0 L	41 Vol	50 FPS 	========
22 In	-10 D	82 R	0 L	40 Vol	50 FPS 	=====
26 In	4 D	88 R	0 L	42 Vol	50 FPS 	======
24 In	-2 D	87 R	0 L	37 Vol	50 FPS 	======
19 In	-5 D	76 R	0 L	42 Vol	50 FPS 	====
23 In	4 D	84 R	0 L	39 Vol	50 FPS 	=====
28 In	5 D	93 R	0 L	42 Vol	50 FPS 	=======
20 In	-8 D	79 R	0 L	38 Vol	50 FPS 	=====

With both chips removed:
Code:
77 In	-3 D	95 R	88 L	89 Vol	50 FPS 	===============X===
88 In	11 D	106 R	98 L	95 Vol	50 FPS 	===============X======
90 In	2 D	104 R	102 L	86 Vol	50 FPS 	===============X======
73 In	-17 D	96 R	80 L	86 Vol	50 FPS 	===============X==
78 In	5 D	91 R	93 L	89 Vol	50 FPS 	===============X===
88 In	10 D	103 R	101 L	83 Vol	50 FPS 	===============X======
68 In	-20 D	90 R	77 L	88 Vol	50 FPS 	===============X=
67 In	-1 D	92 R	72 L	86 Vol	50 FPS 	===============X
75 In	8 D	93 R	88 L	87 Vol	50 FPS 	===============X==
75 In	0 D	101 R	79 L	84 Vol	50 FPS 	===============X==
68 In	-7 D	87 R	79 L	91 Vol	50 FPS 	===============X=
84 In	16 D	105 R	91 L	89 Vol	50 FPS 	===============X=====

Strange...
 
minor note: your PCB schematic says A8 and A9, but your sketch in post #1 uses A0 and A9 in the define's
 
Teensy 2 no signal or GND:
Code:
0 In	0 D	0 R	7 L	2 Vol	50 FPS 	
0 In	0 D	0 R	7 L	2 Vol	50 FPS 	
0 In	0 D	0 R	6 L	2 Vol	50 FPS 	
0 In	0 D	0 R	6 L	8 Vol	50 FPS 	
0 In	0 D	0 R	6 L	2 Vol	50 FPS 	
0 In	0 D	0 R	6 L	2 Vol	50 FPS 	
0 In	0 D	0 R	6 L	2 Vol	50 FPS 	
0 In	0 D	0 R	6 L	2 Vol	50 FPS 	
0 In	0 D	0 R	6 L	2 Vol	50 FPS 	
0 In	0 D	0 R	5 L	2 Vol	50 FPS

Touching the input:
Code:
2 In	-5 D	21 R	24 L	27 Vol	50 FPS 	
96 In	94 D	136 R	83 L	124 Vol	50 FPS 	###############X########
104 In	8 D	124 R	108 L	104 Vol	50 FPS 	===============X==========
131 In	27 D	164 R	118 L	106 Vol	50 FPS 	###############X###############*
134 In	3 D	167 R	122 L	107 Vol	50 FPS 	===============X===============*=
137 In	3 D	167 R	128 L	103 Vol	50 FPS 	===============X===============*==
134 In	-3 D	166 R	122 L	100 Vol	50 FPS 	===============X===============*=
134 In	0 D	166 R	122 L	100 Vol	50 FPS 	===============X===============*=
132 In	-2 D	164 R	121 L	98 Vol	50 FPS 	===============X===============*=
132 In	0 D	165 R	119 L	97 Vol	50 FPS 	===============X===============*=
90 In	-42 D	114 R	92 L	91 Vol	50 FPS 	===============X======
61 In	-29 D	80 R	75 L	67 Vol	50 FPS 	===============
36 In	-25 D	57 R	52 L	49 Vol	50 FPS 	=========
21 In	-15 D	42 R	38 L	41 Vol	50 FPS 	=====
14 In	-7 D	33 R	33 L	36 Vol	50 FPS 	===
6 In	-8 D	25 R	28 L	31 Vol	50 FPS 	=
2 In	-4 D	20 R	24 L	28 Vol	50 FPS
 
This is not very helpful. I'd connect a defined signal (like a sine with given frequency) to the input of your circuit and see what happens.
We don't have your hardware and need more information. Sure, it might be a endian problem or whatever. Or perhaps the 3.X Teensy is still too fast. Slowing it down by changing the cpu frequency might help. Or add more delays, just to find out if that's the problem.

Or think of simply using the audio library, without the chips..
 
Status
Not open for further replies.
Back
Top