Best way to implement complicated mix of PWM and interrupt?

rootwyrm

Member
So, thanks to Teensy 4.1 @ 600MHz, I now have something that's actually powerful enough to do what I need. I hope. But I'm not sure, and this is where the question comes in.

The super short version is:
  1. 4 x 25kHz PWM signals in, which have to be treated individually -> averaged value
  2. 2 x 25kHz PWM signals out
  3. Read falling line (tachometer output) -> map to much higher values (e.g. 300 -> 9900)
  4. Write higher tachometer values out on 4 pins
Obviously the 25kHz portion is pretty easy; I need 6 pins there. Since I intend to implement a serial on Serial1, I'm using FlexPWM3.1 (28,29) for outputs which can be in sync, FlexPWM4.2 for 2 inputs (2, 3,) FlexPWM2.1 for 1 input (4,) and FlexPWM2.2 for 1 input (5.)
Which is where the first question comes in. Each signal is just enough out of phase that it has to be treated distinctly; can I share two inputs there, or do I need to move pins so that the inputs are on separate FlexPWMs?

Then there's the tachometer signal, which is a falling line (standard fan tach.) The outputs can be fairly lossy - I believe about 15% before there's a problem there. But there's two separate inputs that get mapped to those outputs. Obviously by default the answer there would be "attachInterrupt(pin, func, etc.)" but I'm questioning if that would be the right answer here.
Is there a better way to handle two interrupts like this? (Unfortunately, no, they aren't synchronized and do need to report two different values.)
 
I don't fully understand your objective, but it sounds like you're planning to interrupt on edges. If that's correct, rather than do that, the most accurate way to track the time of input edges is to use input capture. Input capture records the value of a (default) 150-MHz clock at the time of each edge (or just rising or falling), and you can use FlexPWM to accurately produce PWM on the output channels with update as often as every PWM period. Take a look at the FreqMeasureMulti library to see if it meets your needs on the input side. I can't search right now, but there are a bunch of threads about producing PWM with a phase shift relative to an input.
 
I don't fully understand your objective, but it sounds like you're planning to interrupt on edges.
That's partly correct. I clearly did a worse job explaining it than I thought.

A better attempt at a diagram:
Code:
Pin -> Function -> Needed Rate
2 -> PWM Input Group0 -> 25kHz
3 -> PWM Input Group0 -> 25kHz
4 -> PWM Input Group1 -> 25kHz
5 -> PWM Input Group1 -> 25kHz
20 -> Digital Output, Tachometer -> 1000ms, 15% lossy OK
21 -> Digital Output, Tachometer -> 1000ms, 15% lossy OK
22 -> Digital Output, Tachometer -> 1000ms, 15% lossy OK
23 -> Digital Output, Tachometer -> 1000ms, 15% lossy OK
26 -> Tachometer Input -> 1000ms (interrupt, falling)
27 -> Tachometer Input -> 1000ms (interrupt, falling)
28 -> PWM Output -> 25kHz +-3% (needs to be 25kHz or causes buzzing)
29 -> PWM Output -> 25kHz +-3%

The flow required is roughly this:
Read Pin 2, Pin 3 -> Pin2+Pin3/2 -> Write PWM to Pin 28 -> Read Pin 26 -> map(MIN,MAX,EXPECT_MIN,EXPECT_MAX) -> Write same digital Pin 20,21

Basically, there is a unit feeding PWM signal on pins 2-5, which are split into 2 groups. Those inputs get averaged over the group, and then need to be written identically to pin 28 and pin 29. e.g. if 2+3/2 = 255 and 4+5 = 128, then analogWrite(28, 255) and analogWrite(29, 128).
Immediately following that, it should do roughly this:
Code:
void setup() {
    delay(1000);
    volatile int fan0_rpm;
    long fan0_tach = fan0_rpm * 60;

    attachInterrupt(digitalPinToInterrupt(FAN_TACH0), fan0_tach, FALLING);
...
void loop() {
...
    mod0_tach_output = map(fan0_tach, FAN_MIN, FAN_MAX, MOD_MIN, MOD_MAX);
    digitalWrite(20, mod0_tach_output);
    digitalWrite(21, mod0_tach_output);
    fan0_rpm = 0;
}

void fan0_tach() {
    fan0_rpm++;
}

This looks to my eyes, to be the very wrong way to do it. But I'm not sure how to do it in such a way as to leverage the Teensy's potential. I actually thankfully don't need to worry too much about offset beyond "will this cause issues on a shared Flex?" As long as it read and writes at 25kHz, updating every 1 second, then I'm good there.

It looks like FreqMeasureMulti might, in fact, be exactly what I need on the input side, but I'm not sure. Does this look vaguely correct?
Code:
FreqMeasureMulti mod0_pwm0;

void setup() {
    ...
    mod0_pwm0.begin(2);
}

float fan0_pwm_output = 0;

void loop() {
    if (mod0_pwm0.available()) {
        fan0_pwm_output = fan0_pwm_output + mod0_pwm0.read();
    }
    analogWrite(FAN0_PWM_PIN, fan0_pwm_output);
   fan0_pwm_output = 0;
   delay(1000);
}
 
I don't understand why you would call analogWrite() every time loop runs. The PWM output will continue updating indefinitely, so you need to call analogWrite() when you want to change the output.

Likewise, why delay for 1 second? You'll only cause your program to miss many updates from FreqMeasureMulti. Worse yet, next time loop() runs you'll end up reading stale data because FreqMeasureMulti has a small buffer of recent measurements. The buffer is meant to allow programs to be busy with other work for short times, like perhaps logging data to a SD card, and not miss inputs which occurred during that brief time. But 1 second with a 25 kHz waveform is far too long. The buffer won't hold all 25000 measurements which occur over that time.

If you really do want to ignore the input for 1 second, rather than delay(), consider using elapsedMillis. When it's less than 1000, just read and ignore the input. Or perhaps add it to a running average. Don't be shy to use 64 bit double which makes calculations so simple. Teensy 4.1 has a FPU which handles 32 and 64 bit floating point math.

Must admit, I don't really have a clear idea of what your program is really trying to accomplish, but I'm pretty sure you should definitely not use delay(). Use 1 or more elapsedMillis variables and design your loop() function to always be as immediately responsive to input as reasonably possible.
 
You might also consider using analogWriteFrequency() in setup(), so your PWM outputs are at the specific frequency you want. Details here:


I see you wrote "written identically to pin 28 and pin 29". I don't know quite what that means, but my gut feeling is you might want to specify the frequency.

Another PWM detail you may wish to keep in mind is the double buffering that happens in the PWM hardware. When you call analogWrite(), the new setting goes into a buffer within the PWM hardware. The new setting takes effect at the beginning of the next waveform cycle. Whether this has any bearing on "identically", I don't know. But hopefully knowing more about how the hardware really works can help you to achieve your goals.
 
I don't understand why you would call analogWrite() every time loop runs. The PWM output will continue updating indefinitely, so you need to call analogWrite() when you want to change the output.

Likewise, why delay for 1 second? You'll only cause your program to miss many updates from FreqMeasureMulti. Worse yet, next time loop() runs you'll end up reading stale data because FreqMeasureMulti has a small buffer of recent measurements. The buffer is meant to allow programs to be busy with other work for short times, like perhaps logging data to a SD card, and not miss inputs which occurred during that brief time. But 1 second with a 25 kHz waveform is far too long. The buffer won't hold all 25000 measurements which occur over that time.

If you really do want to ignore the input for 1 second, rather than delay(), consider using elapsedMillis. When it's less than 1000, just read and ignore the input. Or perhaps add it to a running average. Don't be shy to use 64 bit double which makes calculations so simple. Teensy 4.1 has a FPU which handles 32 and 64 bit floating point math.

Must admit, I don't really have a clear idea of what your program is really trying to accomplish, but I'm pretty sure you should definitely not use delay(). Use 1 or more elapsedMillis variables and design your loop() function to always be as immediately responsive to input as reasonably possible.
See, this is the kind of insight I'm in need of. The problem I have is I'm coming from a very different setup where I can get 25kHz, but not in a fun way. Or a consistent way. I have to take a sample over time (about 500ms,) stuff that value into memory, then update the output. So it's a much slower update rate, a lot less reliable overall. And it doesn't have stable PWM output, forget long. ;)

So if I understand correctly, on the Teensy4.1, I would be good with something more akin to this. But my question then is, how can I read the current configuration of the output pin to compare it?
C:
FreqMeasureMulti mod0_pwm0, mod0_pwm1, fan0_pwm;
elapsedMillis tach0_timer;

void setup() {
    mod0_pwm0.begin(MOD0_PWM0_PIN);
    mod0_pwm1.begin(MOD0_PWM1_PIN);
    attachInterrupt(digitalPinToInterrupt(FAN_TACH0), fan0_tach, FALLING);
}

void loop() {
    // pwm_update will run as fast as possible
    pwm_update()
    ...
    // Then fan tachometer output updates every 1s
    if (tach0_timer > 1000) {
        fan0_write();
    }
}

void pwm_update() {
    float mod0_pwm0, mod0_pwm1;
    if (mod0_pwm0.available()) {
        mod0_pwm0_cur = mod0_pwm0_cur + mod0_pwm0.read();
    }
    if (mod0_pwm1.available()) {
        mod0_pwm1_cur = mod0_pwm1_cur + mod0_pwm1.read();
    }
    fan0_desired = mod0_pwm0_cur + mod0_pwm1_cur / 2;
    // How can I get the current state of the FAN0_PWM pin when it's output?
    if (fan0_desired !=  FAN0_PWM.STATE.QUESTION?) {
        analogWritePin(FAN0_PWM, fan0_pwm_output);
    }
}
I see you wrote "written identically to pin 28 and pin 29". I don't know quite what that means, but my gut feeling is you might want to specify the frequency.
This part is a little funky, but a little easy at the same time? I'm not sure how quite to describe it better, and the part I'm having the most trouble with. Basically there are 2 tachometer inputs from fans, which is a falling edge. Those need mapped to a different range, then 4 pins need to simulate a tachometer output based on that result. Like the PWM, this needs to update every second or so. Because if there's no observed response to a PWM state change within 5 seconds, the device locks itself into a fault state.
It's basically just a Y junction, except with a map in the middle. Tach goes in, measure for 1s, multiply by 60, mapped, gets sent out. The current implementation just flips two digital pins rapidly at ~300Hz and it's close enough (but very inaccurate.)

If I understand correctly, since this is 3V, FreqMeasureMulti might be the better answer here as well? But how would you recommend implementing the counter? The counter may be subject to slow write (e.g. SDcard,) and absolutely must go through a map. How I do that currently is int fan0_rpm_out = map(fan0_rpm, FAN_MIN_RPM, FAN_MAX_RPM, MOD_MIN_RPM, MOD_MAX_RPM);. The idea of getting away from interrupts wherever possible is exactly what I'm looking for here, since there's going to be interrupts I can't get around later on.
 
But my question then is, how can I read the current configuration of the output pin to compare it?

Maybe you meant input pin?

With output pins, which you control with analogWrite(), you should already know the setting because your code set it. If you need to later have this info, just store it into a variable which you can later use.

But to answer the original question, if you really did mean output pin, there is no easy Arduino function to read back the setting you previously established with analogWrite(). In theory, you could craft code to directly access the PWM timer hardware. But the way the hardware works is quite complex and the code inside analogWrite() translates your simple PWM setting to the more complex info the hardware actually uses. You would need to write code to find the correct registers and undo that translation. Simply storing the data into a variable you can access at any later time is so much simpler.
 
That's the theory of operations, yep. I realize I keep overthinking it. I'm still in the 'way underpowered microcontroller' mindset, where things are so overloaded and constrained that even simple things like memory are a problem. Particularly when the device sending the PWM has some obnoxious quirks. ("Sure, let's set 200% duty cycle for 5 seconds!" and "oh, you expected a continuous signal?" are my favorites.)

But, duh, I'm on a much more powerful platform. So I can actually do the right thing instead of stacking horrible hacks on top of each other. It's a hard habit to break.

With that in mind, and some more reading, it looks like maybe FreqCount might actually be what I want. That one, I have two questions on. One, will FreqCount work reliably with a square wave or should I stick to attachInterrupt? Two, can FreqCount trigger on falling instead of rising like #define MEASURE_TYPE FREQMEASUREMULTI_FALLING?
It would be nice to be able to completely eliminate that interrupt driven code. (May still need it elsewhere, but the 8266's an entirely separate thing.)
 
One, will FreqCount work reliably with a square wave or should I stick to attachInterrupt?
Yes, FreqCount will work reliably with a square wave, but it only supports one pin, so it's probably not what you want. For T4.x, FreqCount counts edges on pin 9.
Two, can FreqCount trigger on falling instead of rising like #define MEASURE_TYPE FREQMEASUREMULTI_FALLING?
No, FreqCount is not configurable like that.

I've read through your posts again, and I honestly still don't understand what you're trying to do. In your post #3, it sounds like you have 4 x 25-kHz PWM inputs, and you want to think of them as 2 pairs of 2, and you want to measure the duty cycle of all 4 signals. Is that correct? If you want to measure duty cycle, you should use FreqMeasureMulti. It can measure high time or low time. FreqCount can only tell you the number of PWM periods in a given time, i.e. it can measure frequency of a PWM signal, but not duty cycle.

Once you have the duty cycle of the 4 x PWM inputs, is it your objective to produce 2 x PWM output at the same frequency (25 kHz), with some duty cycle that is a function of the duty cycle you measured on the inputs?
 
I've read through your posts again, and I honestly still don't understand what you're trying to do.

I also have no understanding of the context here which makes answering difficult. (the reason I haven't replied to the latest questions)

@rootwyrm - Have you actually connected the signals to your Teensy 4.0 or 4.1 and experimented yet? Maybe a little time spent experimenting can help you become more familiar with the hardware capability...
 
I also have no understanding of the context here which makes answering difficult. (the reason I haven't replied to the latest questions)

@rootwyrm - Have you actually connected the signals to your Teensy 4.0 or 4.1 and experimented yet? Maybe a little time spent experimenting can help you become more familiar with the hardware capability...

Yep, I've been experimenting a couple days now with my oscilloscope, which honestly has ended up raising more questions than answers so far.
I'm really not sure how better to describe the context; essentially it's a motor controller, except it takes input from a device, passes the PWM portion verbatim to another motor, reads the tachometer output of that motor, converts it to the expected range of the device, and outputs it back to the device. The circuit's not that complex, but maybe a flow chart will make things clearer.

1714849444859.png


I have some more parts on the way, but so far while temporarily wired, it's very much not behaving the way I'd expect it to. But at the moment I'm also using the USB connector frame as the ground for the oscilloscope, so maybe that's a factor? (I'm not sure; the Thermal Control System by the way has some of the most extremely isolated grounds you're ever gonna see and horrible access. So doing in-circuit measuring and testing on that side is basically impossible.)

But, for example, this code isn't behaving even remotely how I'd expect. I basically rewrote as absolute minimum after spending two days troubleshooting why my pwm update routine wasn't working as expected:
Code:
void setup() {
  Serial.begin(9600);
  pinMode(29, OUTPUT);
  analogWriteResolution(12);
  analogWriteFrequency(29, 25000.00);
}
elapsedMillis print_timer;
void loop() {
  // put your main code here, to run repeatedly:
  int value = 4095;
  update_analog(value);
  if (print_timer > 1000)
  {
    Serial.print("Heartbeat ");
    Serial.println(print_timer);
    print_timer = 0;
  }
}
void update_analog(int value)
{
  analogWrite(29, value);
}

The expectation is that I should see 100% duty cycle at 25kHz. Well, 1 out of 3 isn't bad? The oscilloscope actually shows an EXTREMELY unstable signal at 25kHz. About 3 bursts with a big ramp every 250ms, with randomly interspersed long (100-150ms) periods of -0.88V and bounces up to +0.12V on pin 28 and 29. It's definitely not outputting a stable signal at all.

When I change it to 8 bit resolution, it works fine though:
Code:
void setup() {
  Serial.begin(9600);
  pinMode(29, OUTPUT);
  analogWriteResolution(8);
  analogWriteFrequency(29, 25000.00);
}
elapsedMillis print_timer;
void loop() {
  // put your main code here, to run repeatedly:
  int value = 255;
  update_analog(value);
  if (print_timer > 1000)
  {
    Serial.print("Heartbeat ");
    Serial.println(print_timer);
    print_timer = 0;
  }
}
void update_analog(int value)
{
  analogWrite(29, value);
}

Now, my understanding here is that 12 bit resolution should more or less just work. But if I change the first code from 12 to 8, and 4095 to 255, I get stable output. And according to the docs, 36621.09 Hz should be fine with the CPU at 450 or 600MHz. But instead what I'm seeing is that anything besides analogWriteResolution(8); is extremely unstable. 9, 10, 11, 12, all have huge gaps in the output and random long periods.
I'm utterly perplexed there - what am I missing that is causing anything above 8 bit to be completely unstable?
 
I'm utterly perplexed there - what am I missing that is causing anything above 8 bit to be completely unstable?

pinMode() is for digital I/O, so you don't need it. If I remove that and the Serial stuff, your program reduces to what is shown below, continuously calling analogWrite(). I benchmarked it, and T41 can call analogWrite() about 25 million times per second, or 1000 times your PWM frequency, which is probably not what you want. Even so, I used FreqMeasureMulti to count and measure PWM periods, and I get the right count and period for the PWM. I tried it with both 8-bit and 12-bit PWM, and various duty cycles, and got the same result each time. So, you may be right that your scope ground is bad.

Please take Paul's advice and do some testing with just a T4.1, as opposed to testing on your hardware.

Code:
void setup() {
  analogWriteResolution(8);
  analogWriteFrequency(29, 25000.00);
}

void loop() {
  analogWrite(29, 255);
}
 
The expectation is that I should see 100% duty cycle at 25kHz. Well, 1 out of 3 isn't bad? The oscilloscope actually shows an EXTREMELY unstable signal at 25kHz.

I ran your program (the first on msg #11) on a Teensy 4.1. This is the waveform my scope sees on pin 29.

Looks like a very stable 25 kHz waveform. My scope says the duty cycle is 99.97%. That's very close to 4095 / 4096 = 0.999756.


file.png



About 3 bursts with a big ramp every 250ms, with randomly interspersed long (100-150ms) periods of -0.88V and bounces up to +0.12V on pin 28 and 29. It's definitely not outputting a stable signal at all.

I can't see anything like this. But I have a theory... when you "zoom out" by adjusting the horizontal scale so you can see 150ms, perhaps your scope is using a much slower sampling rate? My scope does this because the buffer (or "record length" in oscilloscope lingo) is fixed at 4 Msample. It just can't store the maximum sample rate (5 GSample/sec on my scope) over 150ms because that would require a 750 Msample. It must slow down to a lower sample rate due to the fixed size buffer and longer time scale.

Consider your PWM is 25 kHz and the precision is 1/4096. So the effective maximum fundamental frequency of your waveform is 25000 * 4096 =~ 102 MHz. By Nyquist sampling theory, your scope must sample the signal at a speed of 204 Msample/sec just to capture the fundamental frequency of the narrow pulse. Of course it's a rectangle which means lots of 3rd, 5th, 7th harmonic needs to be captured if you want to see it accurately represented (when you zoom in).

Not all scopes are created equal. When forced to store at a slower sample rate, some will do better than others at capturing details and rendering. Here's what my scope shows if I "zoom out" to view 500 ms across the screen. Notice the scope says the captured data is only 4 Msample/sec, not even 1/50th of sample rate required by Nyquist theory to represent just the fundamental frequency.

file2.png


Of course the image looks terrible, but it is not an accurate representation of the signal because the sample rate is far too slow to capture such a narrow pulse. As I turn the horizontal scale knob, it's easy to see the signal becomes pretty consistent once zoomed in to a time scale where the sample rate is high enough.

While I can't see your screen and I don't have a clear idea of what "an EXTREMELY unstable signal ... with a big ramp every 250ms, with randomly interspersed long (100-150ms) periods of -0.88V and bounces up to +0.12V" really means, my guess is your scope probably is set to a much smaller record length and probably handles the display very badly.

Main point is unless your scope has a huge record length (like 1 Gsample) and actually is fully utilizing it for the rendered image (I'm not aware of any scope which can do such a thing but if it exists I'd really like to know) the image you're seeing is probably very unreliable because of Nyquist aliasing within your scope. This is simply the nature of limitations in all digital oscilloscopes.
 
On 2nd though, perhaps my bandwidth estimation is off by a factor of 2. The narrow pulse would be half of a cycle of a square wave. Maybe.

When you use only 8 bit PWM, the 255 / 256 = 99.6% duty cycle, which is a pulse 16X wider. So it needs only 1/16th the sampling speed to faithfully represent.

While this is just blind guesswork since I can't see your scope screen or know the settings your scope is actually using, I'm pretty sure Teensy's PWM waveforms really are correct and consistent for both 8 and 12 bits, but your scope (probably) doesn't have a high enough sample rate and/or long enough record length to probably show you the 12 bit waveform, at whatever horizontal scale you're using (100-150ms mentioned ... no scope is that good).
 
Last edited:
I ran your program (the first on msg #11) on a Teensy 4.1. This is the waveform my scope sees on pin 29.

Looks like a very stable 25 kHz waveform. My scope says the duty cycle is 99.97%. That's very close to 4095 / 4096 = 0.999756.


View attachment 34201

Yeah, and at this point, I have several VERY inexplicable behaviors going on. PWM signal isn't stable there on either the handheld or bench unit; both show the same instability with wide, wide gaps.

This program doesn't work as expected either:
Code:
const int tachoPin = 36;
volatile unsigned long count = 0;
void setup() {
  Serial.begin(9600);
  pinMode(36, INPUT);
  attachInterrupt(digitalPinToInterrupt(tachoPin), countPulses, FALLING);
  analogWriteResolution(12);
  analogWriteFrequency(28, 25000.0);
  analogWrite(28, 255);
  Serial.println("Startup");
}
elapsedMillis timer;
void loop() {
  long rpm = count / 2 * 60;
  Serial.print("rpm ");
  Serial.println(rpm);
  timer = 0;
  count = 0;
  delay(1000);
}
void countPulses() {
  count ++;
}

And it doesn't work in VERY strange ways. With absolutely nothing connected on pin 28 or pin 36, it's popping a 12-20kHz signal reporting RPMs in the 300,000-500,000 range. I can actually see it out of pin 36 with my oscilloscope. And again: that's with nothing connected but the USB cable. When the analogWrite is removed, it SOMETIMES reports correctly with a 40Hz (1200RPM) signal. But it NEVER reports correctly above that; a 6000RPM signal is somehow getting mangled into 18,000-36,000 without the PWM output connected. With the PWM output connected, it's all over the place - 280,000 to 650,000. Sometimes when you attach the scope, it drops, or it goes higher.

And unfortunately, it's definitely not my scopes. Portable and bench both showed it; wish I'd grabbed some snapshots. It just straight up quits sending anything for anywhere from 100ms to 500ms, and when that happens, I'm seeing the cut in all the way down at 0.5mV and eventually ramping to 2.8-3.0V over 50-125ms. Wildly inconsistent, and not even remotely pushing the limits of the scope. You could see the flat line clearly over 100ms+ on basic 1s 1V sampling. Only rarely looking like yours and what we'd expect. Grabbed one of my Arduino Uno R4's to confirm the scope because of how weird it was.

So, we know what I wrote should work. But this specific Teensy just doesn't behave as it should and isn't very consistent with it. I haven't touched it with a soldering iron. And has actually crashed in watchdog when memory or timers are poked at more firmly. Even examples aren't working consistently or reliably. I even tried changing the power in case it was dirty 5V, a different USB cable, a different host, and so on.
I think it's safe to say I stumbled into a defective one or one that was damaged during handling. I can't see anything physically wrong, but it's the only thing that makes sense. And hey! It happens. I'm local to my Microcenter so exchanging is no big deal, and I have another on the way already.
I'm just happy to know I'm NOT going insane and I did read the docs correctly.
 
With absolutely nothing connected on pin 28 or pin 36,

Your program configured pin 36 as INPUT. With nothing connected, the pin can randomly pick up all sorts of noise. Use INPUT_PULLUP. Or connect a real resistor to the pin. Do not leave high impedance input pins floating.
 
Please shot a screenshot or photo of the screen.
Here's analogWriteResolution(12); analogWrite(28, 4095.0);. Which, yeah, this is definitely not right. No amount of interpolation - even on a budget scope - can explain this one. And no, that's not quite what it looked like before either. Pretty similar though. And obviously not correct.
PIC_11.png

Now here's analogWriteResolution(12); analogWrite(28, 2047.0);. Which, yep, looks right to me. (It does look exactly right as you narrow the time.)
PIC_12.png


edit: rip me, didn't see a bridge that was crossing the reference tach over. Wups.

And here on the left, 25kHz, resolution 8, value 255. On the right, 25kHz, resolution 12, value 4095. Meaning, both are equivalent to a PWM duty cycle of 100%. So these should look identical. (The gap on the right in both is scan update, so ignore that part.) Obviously, the left side looks like what we'd expect with this much of a window. But the right is "wow, what?"

PIC_15.png
PIC_16.png

Your program configured pin 36 as INPUT. With nothing connected, the pin can randomly pick up all sorts of noise. Use INPUT_PULLUP. Or connect a real resistor to the pin. Do not leave high impedance input pins floating.
Yes, sorry, forgot to mention it was doing that with a pull-down to terminate and not showing on the other side of the 10K resistor. So the weird signal was PCB-local.
 
Last edited:
Back
Top