Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Seeed XIAO PWM Issue/Questions #551

Open
fujexo opened this issue Dec 19, 2021 · 4 comments
Open

Seeed XIAO PWM Issue/Questions #551

fujexo opened this issue Dec 19, 2021 · 4 comments

Comments

@fujexo
Copy link

fujexo commented Dec 19, 2021

Hi!

For controlling a LED strip, I need to use PWM. I've got a Seed XIAO MCU which I'm trying to use for this because it's small and fits into the original controller case. Also it has rust support 🎉

Unfortunately, I'm not able to generate the PWM output using rust (A small example with Arduino proofed that it works). I'm not understanding the Alternate Pin functions and probably using them wrong. Also, I don't get where the pins are assigned to the PWM Channel 0 (magic?).

This is my code so far, I've tried to get it together from other BSP examples.

#![no_main]
#![no_std]

extern crate panic_halt;

use hal::{clock::GenericClockController, delay::Delay, prelude::*};
use pac::{CorePeripherals, Peripherals};

use bsp::{
    hal::{
        pwm::{Channel, Pwm0}, 
        self, 
        gpio::{
            v2::{AlternateE, PA07, PA05, Pin}
        }
    }, 
    entry, 
    pac
};
use xiao_m0 as bsp;


#[entry]
fn main() -> ! {
    let mut peripherals = Peripherals::take().unwrap();
    let core = CorePeripherals::take().unwrap();

    let mut clocks = GenericClockController::with_internal_32kosc(
        peripherals.GCLK,
        &mut peripherals.PM,
        &mut peripherals.SYSCTRL,
        &mut peripherals.NVMCTRL,
    );
    let mut delay = Delay::new(core.SYST, &mut clocks);
    let pins = bsp::Pins::new(peripherals.PORT);

    let _a8: Pin<PA07, AlternateE> = pins.a8.into_alternate();
    let _a9: Pin<PA05, AlternateE> = pins.a9.into_alternate();

    let gclk0 = clocks.gclk0();
    let mut pwm0 = Pwm0::new(
        &clocks.tcc0_tcc1(&gclk0).unwrap(),
        1.khz(),
        peripherals.TCC0,
        &mut peripherals.PM,
    );
    let max_duty = pwm0.get_max_duty();

    loop {
        pwm0.set_duty(Channel::_0, max_duty / 2);
        delay.delay_ms(1000u16);
        pwm0.set_duty(Channel::_0, max_duty / 8);
        delay.delay_ms(1000u16);
    }
}
@bradleyharden
Copy link
Contributor

I haven't used the PWM code at all, so I can't be much help. But have you tried using a TC instead of a TCC? Maybe there's a bug in the TCC code that hasn't been caught, because most people use TC.

@fujexo
Copy link
Author

fujexo commented Dec 19, 2021

Thanks for your feedback!
It is unclear for me how to use a TC on these pins. I think I now get how the pin assignment magic happens, I found this table in the datasheet on page 21 where my used pins (A8, A9) are assigned to TCC0/TCC1.
To use for example TC3, I would have to select other pins, is that right?

I also just found something interesting. Because I started to distrust myself, I've written a simple blinky program to verify my pins:

#[entry]
fn main() -> ! {
    let mut peripherals = Peripherals::take().unwrap();
    let core = CorePeripherals::take().unwrap();

    let mut clocks = GenericClockController::with_internal_32kosc(
        peripherals.GCLK,
        &mut peripherals.PM,
        &mut peripherals.SYSCTRL,
        &mut peripherals.NVMCTRL,
    );
    let mut delay = Delay::new(core.SYST, &mut clocks);
    let pins = bsp::Pins::new(peripherals.PORT);

    let mut a8 = pins.a8.into_push_pull_output();
    let mut a9 = pins.a9.into_push_pull_output();

    a8.set_low().unwrap();
    a9.set_low().unwrap();

    loop {

        a8.set_high().unwrap();
        delay.delay_ms(1000u16);
        a8.set_low().unwrap();
        delay.delay_ms(1000u16);

        a9.set_high().unwrap();
        delay.delay_ms(1000u16);
        a9.set_low().unwrap();
        delay.delay_ms(1000u16);

    }
}

For some reason, my LEDs are driven when nothing is pulling the pins down (might be my level shifter - topic for after the coding). So I've noticed that when set both these pins to alternate mode E (which I found in the datasheet is TC/TCC, finally found the explanation to the alternate modes :)), the Warm LED turns off (probably because the pin is set to low) and the cold LED is staying on. Can't find an explanation to this after the blinky program worked fine and I think it should be the same for both of the pins, right?

    let _cold_led = pins.a8.into_alternate::<E>();
    let _warm_led = pins.a9.into_alternate::<E>();

@bradleyharden
Copy link
Contributor

It is unclear for me how to use a TC on these pins. ... To use for example TC3, I would have to select other pins, is that right?

Correct. I assumed your could find some other pins to try out, but I don't know your board at all.

In your latest example, it sounds like you're trying to use AlternateE mode without using the TCC, is that right? I don't know what would happen in that case. It probably depends on the default state of the TCC peripheral. Are there any dedicated LEDs on the board? Could you use those for a blinky example?

The best way to diagnose the PWM issue is probably to reproduce one of the TC examples on a different set of pins (if you can find one). At least that's probably what I would do.

@bradleyharden
Copy link
Contributor

@fujexo, any progress with this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants