Giter Club home page Giter Club logo

Comments (17)

eldruin avatar eldruin commented on June 9, 2024 1

Hi @Nivek92,
Thanks for the detailed debugging. The values seem correct:

 0 -> LED0_ON_L
 0 -> LED0_ON_H
 58 -> LED0_OFF_L
 02 -> LED0_OFF_H

This means LED0 on at 0 and off at 570.

I just noticed in your last snippet the call to enable is missing.
Could you add that and try again?

I also noticed it is also missing in the driver examples in the documentation. I have noted it and will fix that soon.

from pwm-pca9685-rs.

Nivek92 avatar Nivek92 commented on June 9, 2024 1

Hey @eldruin,
with pwm.enable().unwrap(); it's actually working. Thank you.

I certainly tried it with pwm.enable().unwrap(); before on my STM32 which didn't work, really weird but now that I have a working reference and the logic analyzer I will also give it another try on the STM32 and report back if there is still a problem.

from pwm-pca9685-rs.

Nivek92 avatar Nivek92 commented on June 9, 2024 1

Ok no worries.

I also tried it with my STM32F401CEU6, on which it works as well. So it's just the blue pill with the fake chip which does not work.

As it's working with the raspberry pi and the STM32F401 I will move on for now and maybe try to solve the mystery at some other point in time.

Thanks for your time and help. Appreciate it.

from pwm-pca9685-rs.

eldruin avatar eldruin commented on June 9, 2024

If you can dim LEDs that means that the address is correct and the communication is working so the difficult part is over. Maybe there is a problem with the math functions.
I would recommend getting rid of all that and just get one servo to move to a certain position and then work from there.
You can see servos working in this video. Here is the program running there. Also just an STM32F103 "blue pill" board and a PCA9685.

from pwm-pca9685-rs.

Nivek92 avatar Nivek92 commented on June 9, 2024

I tried the example code before but the servos aren't working. I debugged the code and checked the entries in the values array and they look fine.

I also noticed running the example code all PWM pins on the PCA9685 output the same signal. (Although pins 6,7,8,9 and 15 should be low the whole time.)

Any ideas how to troubleshoot?

from pwm-pca9685-rs.

eldruin avatar eldruin commented on June 9, 2024

You can try checking what is actually transmitted in the I2C bus and how the PWM pulses look like with a logic analyzer.

from pwm-pca9685-rs.

Nivek92 avatar Nivek92 commented on June 9, 2024

Yo, I received a logic analyzer so I will try to analyze the signal.

In the meantime I also tried it on my Raspberry Pi Zero. As a reference I used some python code which works and then tried some rust code which should be equal.

Here's the working python code

from __future__ import division
import time

import Adafruit_PCA9685

pwm = Adafruit_PCA9685.PCA9685()

servo_min = 150  # Min pulse length out of 4096
servo_max = 600  # Max pulse length out of 4096

pwm.set_pwm_freq(60)

while True:
    pwm.set_pwm(0, 0, servo_min)
    time.sleep(1)
    pwm.set_pwm(0, 0, servo_max)
    time.sleep(1)

and the not working rust code

use embedded_hal::blocking::delay::DelayMs;
use linux_embedded_hal::{Delay, I2cdev};
use pwm_pca9685::{Address, Channel, Pca9685};

fn main() {
    let dev = I2cdev::new("/dev/i2c-1").unwrap();
    let address = Address::default();
    let mut pwm = Pca9685::new(dev, address).unwrap();

    let servo_min = 150;
    let servo_max = 600;

    let mut delay = Delay;

    // This corresponds to a frequency of 60 Hz.
    pwm.set_prescale(100).unwrap();

    loop {
        pwm.set_channel_on_off(Channel::C0, 0, servo_min).unwrap();
        delay.delay_ms(1000u16);
        pwm.set_channel_on_off(Channel::C0, 0, servo_max).unwrap();
        delay.delay_ms(1000u16);
    }
}

Do I miss something?

from pwm-pca9685-rs.

Nivek92 avatar Nivek92 commented on June 9, 2024

I recorded the output of the above code via a logic analyzer.

The first is the output from the python code, which works, and the second is from the rust code, which does not work.

python - working

rust - not working

from pwm-pca9685-rs.

eldruin avatar eldruin commented on June 9, 2024

I'm glad to hear that :)

from pwm-pca9685-rs.

Nivek92 avatar Nivek92 commented on June 9, 2024

Ok, so I tried on the STM32 and there it does not work.

Here is the code

#![deny(unsafe_code)]
#![no_std]
#![no_main]

use cortex_m_rt::entry;
use panic_semihosting as _;
use pwm_pca9685::{Address, Channel, Pca9685};
use stm32f1xx_hal::{
    delay::Delay,
    i2c::{BlockingI2c, DutyCycle, Mode},
    pac,
    prelude::*,
};

#[entry]
fn main() -> ! {
    let cp = cortex_m::Peripherals::take().unwrap();
    let dp = pac::Peripherals::take().unwrap();

    let mut flash = dp.FLASH.constrain();
    let mut rcc = dp.RCC.constrain();

    let clocks = rcc.cfgr.freeze(&mut flash.acr);
    let mut afio = dp.AFIO.constrain(&mut rcc.apb2);
    let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);

    let scl = gpiob.pb8.into_alternate_open_drain(&mut gpiob.crh);
    let sda = gpiob.pb9.into_alternate_open_drain(&mut gpiob.crh);
    let mut delay = Delay::new(cp.SYST, clocks);

    let i2c = BlockingI2c::i2c1(
        dp.I2C1,
        (scl, sda),
        &mut afio.mapr,
        Mode::Fast {
            frequency: 400_000.hz(),
            duty_cycle: DutyCycle::Ratio2to1,
        },
        clocks,
        &mut rcc.apb1,
        1000,
        10,
        1000,
        1000,
    );

    let mut pwm = Pca9685::new(i2c, Address::default()).unwrap();
    pwm.enable().unwrap();
    pwm.set_prescale(100).unwrap();

    let servo_min = 150;
    let servo_max = 600;

    loop {
        pwm.set_channel_on_off(Channel::C0, 0, servo_min).unwrap();
        // delay
        delay.delay_ms(1000u16);
        pwm.set_channel_on_off(Channel::C0, 0, servo_max).unwrap();
        // delay
        delay.delay_ms(1000u16);
    }
}

memory.x

MEMORY
{
  FLASH : ORIGIN = 0x08000000, LENGTH = 64K
  RAM : ORIGIN = 0x20000000, LENGTH = 20K
}

.cargo/config

[target.thumbv7m-none-eabi]
runner = 'gdb-multiarch'
rustflags = [
  "-C", "link-arg=-Tlink.x",
]

[build]
target = "thumbv7m-none-eabi"

As you can see the frequency is much higher and there are more packets being sent so I couldn't get everything on the screenshot.

All data writes are duplicated. Is this because of DutyCycle::Ratio2to1?

stm32 - close up
stm32

from pwm-pca9685-rs.

eldruin avatar eldruin commented on June 9, 2024

I will check on this later.
In the mean time, you can change the communication mode to standard with:

Mode::Standard {
    frequency: 100_000.hz(),
}

from pwm-pca9685-rs.

Nivek92 avatar Nivek92 commented on June 9, 2024

Actually tried that already. But the output looks similar.

from pwm-pca9685-rs.

eldruin avatar eldruin commented on June 9, 2024

What kind of board do you have?
Is anything else connected to the I2C bus?
Have you tried adding two 10kOhm or 4.7kOhm pull-up resistors to the SCL and SDA lines?

from pwm-pca9685-rs.

Nivek92 avatar Nivek92 commented on June 9, 2024

Ok, so first off I am an idiot.

The above measurement showed such a high frequent signal because I was running the wrong code. I build in release but loaded from the debug directory. After deploying the correct code it looks much better but it's still not working.

As you can see below it looks nearly the same as the working signal on the raspberry pi but there is a double data write of 06 instead of a single.

stm32 - not working

And to answer your above questions.

The board is a blue pill but instead of the original STM32 chip it has a CH32 chip but I don't think that makes the difference here.

There is nothing connected to I2C besides the PCA9695 and the logic analyzer.

I tried both 10k and 4.7k pull-up resistors but it didn't make a difference.

Oh and here is the currect code

#![deny(unsafe_code)]
#![no_std]
#![no_main]

use cortex_m_rt::entry;
use panic_semihosting as _;
use pwm_pca9685::{Address, Channel, Pca9685};
use stm32f1xx_hal::{
    delay::Delay,
    i2c::{BlockingI2c, DutyCycle, Mode},
    pac,
    prelude::*,
};

#[entry]
fn main() -> ! {
    let cp = cortex_m::Peripherals::take().unwrap();
    let dp = pac::Peripherals::take().unwrap();

    let mut flash = dp.FLASH.constrain();
    let mut rcc = dp.RCC.constrain();

    let clocks = rcc.cfgr.freeze(&mut flash.acr);
    let mut afio = dp.AFIO.constrain(&mut rcc.apb2);
    let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);

    let scl = gpiob.pb8.into_alternate_open_drain(&mut gpiob.crh);
    let sda = gpiob.pb9.into_alternate_open_drain(&mut gpiob.crh);
    let mut delay = Delay::new(cp.SYST, clocks);

    let i2c = BlockingI2c::i2c1(
        dp.I2C1,
        (scl, sda),
        &mut afio.mapr,
        Mode::Fast {
            frequency: 400_000.hz(),
            duty_cycle: DutyCycle::Ratio2to1,
        },
        clocks,
        &mut rcc.apb1,
        1000,
        10,
        1000,
        1000,
    );

    let mut pwm = Pca9685::new(i2c, Address::default()).unwrap();
    pwm.enable().unwrap();
    pwm.set_prescale(100).unwrap();

    let servo_min = 150;
    let servo_max = 600;

    loop {
        pwm.set_channel_on_off(Channel::C0, 0, servo_min).unwrap();
        // delay
        delay.delay_ms(1000u16);
        pwm.set_channel_on_off(Channel::C0, 0, servo_max).unwrap();
        // delay
        delay.delay_ms(1000u16);
    }
}

Also tried the regulat i2c more with 100khz. No difference.

Edit: accidentally closed the issue instead of submitting the comment (was a long day :D)

from pwm-pca9685-rs.

eldruin avatar eldruin commented on June 9, 2024

Hi @Nivek92,
I just built this with a blue-pill, a PCA9685 and one servo similar like in the picture here and your code works fine.
Both in fast and standard mode the servo moves from one side to the other as expected, no extra pull-ups needed for me.
In fast mode pulseview could not decode the protocol well but in standard it does. You can see there is no extra 06:

sc1
sc2

This worked fine both in release and debug mode.
What I did is just this:

  1. openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
  2. git clone https://github.com/eldruin/driver-examples
  3. cd driver-examples/stm32f1-bluepill
  4. nano examples/pca9685.rs
  5. Paste your code and save
  6. cargo run --example pca9685

Can you try it this way to ensure your problem is not caused by some difference in one of the crates used?

from pwm-pca9685-rs.

Nivek92 avatar Nivek92 commented on June 9, 2024

Ok, I cloned the above repo and inserted my code, the results are rather interesting. Unfortunately the servo does not move.

When I run it in fast mode I get the correct data writes but still with this weird duplication.

stm32 - fast mode

When I run it in standard mode I get the duplicated 06 data write but not the weird duplication.
stm32 - standard mode

from pwm-pca9685-rs.

eldruin avatar eldruin commented on June 9, 2024

I do not know what the problem on your side might be. I cannot reproduce it so I am afraid I cannot provide any further help.

from pwm-pca9685-rs.

Related Issues (8)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.