A0 on CPX

Play with it! Please tell us which board you're using.
For CircuitPython issues, ask in the Adafruit CircuitPython forum.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
christopherv
 
Posts: 32
Joined: Wed Jan 08, 2014 4:56 pm

A0 on CPX

Post by christopherv »

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?
Attachments
Screen Shot 2018-10-27 at 10.58.56 PM.png
Screen Shot 2018-10-27 at 10.58.56 PM.png (41.31 KiB) Viewed 496 times

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: A0 on CPX

Post by adafruit_support_mike »

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)?

User avatar
christopherv
 
Posts: 32
Joined: Wed Jan 08, 2014 4:56 pm

Re: A0 on CPX

Post by christopherv »

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.

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);
  }
}
When limit is 256, I get the triangular waveform shown in the first image.
When max value to analogWrite() is 255.
When max value to analogWrite() is 255.
limit_256.png (280.66 KiB) Viewed 456 times
When the limit is 1024, i get the 'jumpy' waveform shown in the second image.
When max value to analogWrite() is 1024.
When max value to analogWrite() is 1024.
limit_1024.png (300.81 KiB) Viewed 456 times
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.

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);
  }
}
Here's what the Serial monitor shows when setup() runs, verifying that values up to 255 are being written:

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
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.
Attachments
sine_11K.h
Header file for sine wave generator.
(60.1 KiB) Downloaded 41 times

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: A0 on CPX

Post by adafruit_support_mike »

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:

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);
  }
That will give you the most direct view of what's going to the DAC.

User avatar
christopherv
 
Posts: 32
Joined: Wed Jan 08, 2014 4:56 pm

Re: A0 on CPX

Post by christopherv »

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
Waveform
2018-11-07_truncated_sine.png (763.74 KiB) Viewed 433 times
Serial output
Serial output
Screen Shot 2018-11-07 at 5.27.00 PM.png (156.23 KiB) Viewed 433 times

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: A0 on CPX

Post by adafruit_support_mike »

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:

Code: Select all

      digitalWrite(speaker_enable, digitalRead(slide_switch));
inside the loop. Try moving that to setup() so it's completely out of the loop that generates the waveform.

User avatar
christopherv
 
Posts: 32
Joined: Wed Jan 08, 2014 4:56 pm

Re: A0 on CPX

Post by christopherv »

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.

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);
  }
}
I'm confused!

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: A0 on CPX

Post by adafruit_support_mike »

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.

User avatar
christopherv
 
Posts: 32
Joined: Wed Jan 08, 2014 4:56 pm

Re: A0 on CPX

Post by christopherv »

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.
DSO Nano connected to CPX.
Hardware Setup.png (581.16 KiB) Viewed 393 times

User avatar
christopherv
 
Posts: 32
Joined: Wed Jan 08, 2014 4:56 pm

Re: A0 on CPX

Post by christopherv »

Forgot to mention that I did try with a different CPX with the same results.

User avatar
kevinjwalters
 
Posts: 1025
Joined: Sun Oct 01, 2017 3:15 pm

Re: A0 on CPX

Post by kevinjwalters »

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?

User avatar
christopherv
 
Posts: 32
Joined: Wed Jan 08, 2014 4:56 pm

Re: A0 on CPX

Post by christopherv »

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.

User avatar
christopherv
 
Posts: 32
Joined: Wed Jan 08, 2014 4:56 pm

Re: A0 on CPX

Post by christopherv »

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
A 220 sampled at 4KHz
4K Sampling.png (537.92 KiB) Viewed 375 times

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: A0 on CPX

Post by adafruit_support_mike »

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.

User avatar
kevinjwalters
 
Posts: 1025
Joined: Sun Oct 01, 2017 3:15 pm

Re: A0 on CPX

Post by kevinjwalters »

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.

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);
      }
    }
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.

Locked
Please be positive and constructive with your questions and comments.

Return to “Circuit Playground Classic, Circuit Playground Express, Circuit Playground Bluefruit”