A0 on CPX
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- christopherv
- Posts: 32
- Joined: Wed Jan 08, 2014 4:56 pm
A0 on CPX
I am trying to use Arduino analogWrite() to generate a sine wave on the CPX. The range of intensities to analogWrite() is scaled to 0 to 255 for sine values -1 to +1.
The output voltage never goes above 2.25 volts, and I get the waveform shown in the attached screenshot.
Even if the voltage is limited to 2.25, shouldn't that be produced by 255 as the argument to analogWrite()?
Is this a bug or a feature?
The output voltage never goes above 2.25 volts, and I get the waveform shown in the attached screenshot.
Even if the voltage is limited to 2.25, shouldn't that be produced by 255 as the argument to analogWrite()?
Is this a bug or a feature?
- Attachments
-
- Screen Shot 2018-10-27 at 10.58.56 PM.png (41.31 KiB) Viewed 496 times
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: A0 on CPX
The DAC's output should be able to reach 3.3V.
It's a 10-bit DAC though, so values from 0 to 255 should only produce a sine wave between 0V and about 850mV. Could you post the code you're using (between CODE tags please)?
It's a 10-bit DAC though, so values from 0 to 255 should only produce a sine wave between 0V and about 850mV. Could you post the code you're using (between CODE tags please)?
- christopherv
- Posts: 32
- Joined: Wed Jan 08, 2014 4:56 pm
Re: A0 on CPX
The DAC might be 10-bit, but doing analogWrite(A0, value) where value is greater than 255, the output wraps around as if the left two bits are being ignored.
When limit is 256, I get the triangular waveform shown in the first image.
When the limit is 1024, i get the 'jumpy' waveform shown in the second image.
But in both cases I get a full 3.3 volt peak output.
But I still get the output waveform truncated to 2.25 volts when I try to generate a sine wave.
Here's the code. I've added the header file as an attachment.
Here's what the Serial monitor shows when setup() runs, verifying that values up to 255 are being written:
Given that the saw-tooth code gives the full 3.3 volt range, I realize it looks like my code is to blame for truncating the sine wave output. But I don't see how that's happening.
Any help/insight would be much appreciated.
Code: Select all
void loop()
{
if (millis() - start > 5000)
{
start = millis();
limit = (limit == 256) ? 1024 : 256;
}
for (int i = 0; i < limit; i++)
{
analogWrite(speaker, i);
}
for (int i = limit -1; i >= 0; i--)
{
analogWrite(speaker, i);
}
}
But I still get the output waveform truncated to 2.25 volts when I try to generate a sine wave.
Here's the code. I've added the header file as an attachment.
Code: Select all
#include "sine_11K.h"
#define slide_switch 7
#define speaker_enable 11
#define speaker A0
void setup()
{
pinMode(speaker, OUTPUT);
pinMode(slide_switch, INPUT_PULLUP);
pinMode(speaker_enable, OUTPUT);
digitalWrite(speaker_enable, false);
Serial.begin(9600);
while (!Serial);
int max_value = 0;
for (int i = 0; i < a4.length; i++)
{
Serial.print(i); Serial.print(":\t");
Serial.println(a4.values[i]);
if (a4.values[i] > max_value)
{
max_value = a4.values[i];
}
}
Serial.print("Max value was "); Serial.println(max_value);
}
void loop()
{
for (int i = 0; i < a4.length; i++)
{
digitalWrite(speaker_enable, digitalRead(slide_switch));
analogWrite(speaker, a4.values[i]);
delayMicroseconds(sampling_period);
}
}
Code: Select all
0: 128
1: 159
2: 189
3: 215
4: 235
5: 249
6: 255
7: 253
8: 243
9: 226
10: 202
11: 174
12: 143
13: 111
14: 80
15: 52
16: 29
17: 12
18: 2
19: 0
20: 6
21: 20
22: 41
23: 67
24: 96
Max value was 255
Any help/insight would be much appreciated.
- Attachments
-
- sine_11K.h
- Header file for sine wave generator.
- (60.1 KiB) Downloaded 41 times
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: A0 on CPX
As a sanity check, create a dummy variable and assign the amplitude value to that, then use that for both the DAC setting and a print() statement:
That will give you the most direct view of what's going to the DAC.
Code: Select all
for (int i = 0; i < a4.length; i++)
{
int a = a4.values[ i ];
digitalWrite(speaker_enable, digitalRead(slide_switch));
analogWrite( speaker, a );
Serial.println( a );
delayMicroseconds(sampling_period);
}
- christopherv
- Posts: 32
- Joined: Wed Jan 08, 2014 4:56 pm
Re: A0 on CPX
OK, here's the waveform and Serial output. And to be complete, here's the complete code:
Code: Select all
#include "sine_11K.h"
#define slide_switch 7
#define speaker_enable 11
#define speaker A0
void setup()
{
pinMode(speaker, OUTPUT);
pinMode(slide_switch, INPUT_PULLUP);
pinMode(speaker_enable, OUTPUT);
digitalWrite(speaker_enable, false);
Serial.begin(9600);
while (!Serial);
}
void loop()
{
for (int i = 0; i < a4.length; i++)
{
int a = a4.values[ i ];
digitalWrite(speaker_enable, digitalRead(slide_switch));
analogWrite( speaker, a );
Serial.println( a );
delayMicroseconds(sampling_period);
}
}
- Attachments
-
- Waveform
- 2018-11-07_truncated_sine.png (763.74 KiB) Viewed 433 times
-
- Serial output
- Screen Shot 2018-11-07 at 5.27.00 PM.png (156.23 KiB) Viewed 433 times
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: A0 on CPX
Okay, we've gotten pretty well into "that shouldn't happen" territory, especially since the DAC seems to provide the correct output for other code.
The next most likely point of suspicion is the line:
inside the loop. Try moving that to setup() so it's completely out of the loop that generates the waveform.
The next most likely point of suspicion is the line:
Code: Select all
digitalWrite(speaker_enable, digitalRead(slide_switch));
- christopherv
- Posts: 32
- Joined: Wed Jan 08, 2014 4:56 pm
Re: A0 on CPX
I tried that. I also tried not writing anything at all to pin 11.
Same waveform in all cases.
I also re-ran the other test code (the one that verifies that the second arg to analogWrite() is 8 bits), and see that that one is producing 3.08V p-p, which is neither the 2.25V I see on the sine wave, nor the 3.3V I might expect to be the output of the DAC.
I'm confused!
Same waveform in all cases.
I also re-ran the other test code (the one that verifies that the second arg to analogWrite() is 8 bits), and see that that one is producing 3.08V p-p, which is neither the 2.25V I see on the sine wave, nor the 3.3V I might expect to be the output of the DAC.
Code: Select all
void loop()
{
if (millis() - start > 5000)
{
start = millis();
limit = (limit == 256) ? 1024 : 256;
}
for (int i = 0; i < limit; i++)
{
analogWrite(speaker, i);
}
for (int i = limit -1; i >= 0; i--)
{
analogWrite(speaker, i);
}
}
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: A0 on CPX
Post a photo showing your hardware and connections please. There doesn't seem to be anything wrong with the code, and the signal behavior appears to be changing in unexpected ways, so let's see if there are any possible physical issues.
800x600 images usually work best.
800x600 images usually work best.
- christopherv
- Posts: 32
- Joined: Wed Jan 08, 2014 4:56 pm
Re: A0 on CPX
There's not much to it. A MacBook Pro running MacOs Mojave, the CPX, and the scope, and a blue MFI certified USB cable from Monoprice. The attached photo shows a DSO Nano V3, but I see the same waveform with a Tektronix 2200 series benchtop unit (I don't have the unit with me to check the model number) and on a Saleae Logic Pro 8 logic analyzer in analog mode. I've posted a photos using the Saleae in this thread: it's the first one with the 2.25V "tooltip" showing; other pictures are from the Tektronix.
- Attachments
-
- DSO Nano connected to CPX.
- Hardware Setup.png (581.16 KiB) Viewed 393 times
- christopherv
- Posts: 32
- Joined: Wed Jan 08, 2014 4:56 pm
Re: A0 on CPX
Forgot to mention that I did try with a different CPX with the same results.
- kevinjwalters
- Posts: 1025
- Joined: Sun Oct 01, 2017 3:15 pm
Re: A0 on CPX
If you've run out of things to experiment with, does the sine wave change if you lower the frequency, e.g. increase sampling_period by 20 ?
Another puzzle is why the scope shows 281 Hz when A4 would be 440 Hz? Oh was the additional delay from running digitalWrite(speaker_enable, digitalRead(slide_switch)) in the loop?
Another puzzle is why the scope shows 281 Hz when A4 would be 440 Hz? Oh was the additional delay from running digitalWrite(speaker_enable, digitalRead(slide_switch)) in the loop?
- christopherv
- Posts: 32
- Joined: Wed Jan 08, 2014 4:56 pm
Re: A0 on CPX
Good questions. The first answer is that the digitalWrite(digitalRead(0) code is out of loop() now, so that's not a factor. The second answer is that I tried a3 instead of a4, thereby doubling the sampling interval, and I get the same waveform. The third answer is that the current code is showing a frequency of approximately 420 Hz and 211 Hz for a4 and a3 respectively. I think the digitalWrite(digitalRead()) accounted for some of the frequency inaccuracy, but I didn't look into it further: got distracted by the truncated sine wave.
One other "experiment" was to multiply the intensities by 2/3. That produced a clean signal, albeit attenuated as one would expect.
One other "experiment" was to multiply the intensities by 2/3. That produced a clean signal, albeit attenuated as one would expect.
- christopherv
- Posts: 32
- Joined: Wed Jan 08, 2014 4:56 pm
Re: A0 on CPX
After posting last message I realized that halving the signal frequency did not affect the sampling rate. Previous code use sampling rate of 11025 Hz. I tried with a 4096 Hz sampling rate and got the same peak-limited sine wave, as shown in the attached picture. This was for a A 220.
- Attachments
-
- A 220 sampled at 4KHz
- 4K Sampling.png (537.92 KiB) Viewed 375 times
- adafruit_support_mike
- Posts: 67446
- Joined: Thu Feb 11, 2010 2:51 pm
Re: A0 on CPX
Try putting a 100k-100k voltage divider between A0 and GND and scoping the center of the divider.
My best guess at this point is some kind of loading on the pin, though I'm darned if I know what.
Also try doubling the values you send to the DAC.. let's see how the signals behave when the values wrap around.
My best guess at this point is some kind of loading on the pin, though I'm darned if I know what.
Also try doubling the values you send to the DAC.. let's see how the signals behave when the values wrap around.
- kevinjwalters
- Posts: 1025
- Joined: Sun Oct 01, 2017 3:15 pm
Re: A0 on CPX
I can reproduce this using a Circuit Playground Express, Arduino 1.87 and Arduino SAMD Boards 1.6.19.
A sawtooth also clips in the same way for me.
Some further tests suggest that 186 (perhaps 187, I'm using an ancient, decrepit, analogue 'scope) is the value that mine won't go beyond.
A sawtooth also clips in the same way for me.
Code: Select all
void loop()
{
// one sine
for (int i = 0; i < a4.length; i++)
{
// digitalWrite(speaker_enable, digitalRead(slide_switch));
analogWrite(speaker, a4.values[i]);
delayMicroseconds(sampling_period);
}
two saw
for (int val = 0; val <= 255; val += 4)
{
// digitalWrite(speaker_enable, digitalRead(slide_switch));
analogWrite(speaker, val);
delayMicroseconds(sampling_period);
}
for (int val = 0; val <= 255; val += 4)
{
// digitalWrite(speaker_enable, digitalRead(slide_switch));
analogWrite(speaker, val);
delayMicroseconds(sampling_period);
}
}
Please be positive and constructive with your questions and comments.