Comments (17)
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.
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.
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.
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.
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.
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.
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.
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.
from pwm-pca9685-rs.
I'm glad to hear that :)
from pwm-pca9685-rs.
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
?
from pwm-pca9685-rs.
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.
Actually tried that already. But the output looks similar.
from pwm-pca9685-rs.
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.
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.
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.
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
:
This worked fine both in release and debug mode.
What I did is just this:
- openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
- git clone https://github.com/eldruin/driver-examples
- cd driver-examples/stm32f1-bluepill
- nano examples/pca9685.rs
- Paste your code and save
- 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.
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.
When I run it in standard mode I get the duplicated 06 data write but not the weird duplication.
from pwm-pca9685-rs.
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pwm-pca9685-rs.