95579


ESP32-S3 + esp-halを使ってRustで組み込み開発をしています。  
gpio1,2の電圧をADコンバータを使って取得する構造体を作りたいです。以下のように実装してみましたが、ビルドエラーとなります。

[code]

    #![no_std]
    #![no_main]
    
    use esp_backtrace as _;
    use esp_println::println;
    
    use embedded_hal::adc::{
        Channel,
        OneShot,
    };
    
    use esp32s3_hal::{
        clock::ClockControl,
        peripherals::Peripherals,
        prelude::*,
        timer::TimerGroup,
        Rtc,
        gpio::IO,
        adc::{AdcConfig, Attenuation, ADC, ADC1, RegisterAccess, AdcPin},
    };
    
    struct Sensors<SENADC, ANALOG1, ANALOG2> {
        adc: SENADC,
        pin1: ANALOG1,
        pin2: ANALOG2,
    }
    
    impl<SENADC, PIN1, PIN2, ADCI> Sensors<SENADC, AdcPin<PIN1, ADCI>, AdcPin<PIN2, ADCI>>
        where
            SENADC: OneShot<ADCI, u16, AdcPin<PIN1, ADCI>>,
            PIN1: Channel<ADCI, ID = u8>,
            PIN2: Channel<ADCI, ID = u8>,
            ADCI: RegisterAccess, {
        
        pub fn new( adc: SENADC,
                    pin1: AdcPin<PIN1, ADCI>,
                    pin2: AdcPin<PIN2, ADCI>) -> Self  {
            Sensors {adc: adc, pin1: pin1, pin2: pin2}
        }
    
        pub fn read(&mut self) -> (u16, u16) {
            let v1 = match nb::block!(self.adc.read(&mut self.pin1)){
                Ok(value) => value,
                Err(_) => 0,
            };
    
            let v2 = match nb::block!(self.adc.read(&mut self.pin2)){
                Ok(value) => value,
                Err(_) => 0,
            };
            (v1, v2)
        }
    }
    
    
    #[entry]
    fn main() -> ! {
        let peripherals = Peripherals::take();
        let mut system = peripherals.SYSTEM.split();
        let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
    
        let mut rtc = Rtc::new(peripherals.RTC_CNTL);
        let timer_group0 = TimerGroup::new(
            peripherals.TIMG0,
            &clocks,
            &mut system.peripheral_clock_control,
        );
        let mut wdt = timer_group0.wdt;
    
        wdt.disable();
        rtc.rwdt.disable();
    
        let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
    
        let analog = peripherals.SENS.split();
    
        let mut adc1_config = AdcConfig::new();
    
        let mut pin1 = adc1_config.enable_pin(io.pins.gpio1.into_analog(), Attenuation::Attenuation11dB);
        let mut pin2 = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
        let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
    
        let mut sensors = Sensors::new(adc1, pin1, pin2);
        let (value1, value2) = sensors.read();
        println!("{}, {}",value1, value2);
    
        loop {}
    }
    
[/code]

エラー内容（抜粋）は以下のとおりです。

[code]

    error[E0308]: mismatched types
      --> src/main.rs:47:49
       |
    28 | impl<SENADC, PIN1, PIN2, ADCI> Sensors<SENADC, AdcPin<PIN1, ADCI>, AdcPin<PIN2, ADCI>>
       |              ----  ---- found type parameter
       |              |
       |              expected type parameter
    ...
    47 |         let v2 = match nb::block!(self.adc.read(&mut self.pin2)){
       |                                            ---- ^^^^^^^^^^^^^^ expected `&mut AdcPin<PIN1, ADCI>`, found `&mut AdcPin<PIN2, ADCI>`
       |                                            |
       |                                            arguments to this method are incorrect
       |
       = note: expected mutable reference `&mut AdcPin<PIN1, ADCI>`
                  found mutable reference `&mut AdcPin<PIN2, ADCI>`
       = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
       = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
    note: method defined here
      --> /home/k-iida/.cargo/registry/src/index.crates.io-6f17d22bba15001f/embedded-hal-0.2.7/src/adc.rs:97:8
       |
    97 |     fn read(&mut self, pin: &mut Pin) -> nb::Result<Word, Self::Error>;
       |        ^^^^
    
    For more information about this error, try `rustc --explain E0308`.
    
[/code]

`OneShot`に与えているPINがPIN1なので、このエラーは当然かと思います。しかしpin1とpin2（つまり、gpio1とgpio2）では型が異なるため以下のように書くこともできません。

[code]

    struct Sensors<SENADC, ANALOG> {
        adc: SENADC,
        pin1: ANALOG,
        pin2: ANALOG,
    }
    
    impl<SENADC, PIN, ADCI> Sensors<SENADC, AdcPin<PIN2, ADCI>>
        where
            SENADC: OneShot<ADCI, u16, AdcPin<PIN, ADCI>>,
            PIN: Channel<ADCI, ID = u8>,
            ADCI: RegisterAccess, {
    ...
    
[/code]

一方で、構造体を使わずに以下のように書けばビルドエラーにはなりません。

[code]

        let mut pin1 = adc1_config.enable_pin(io.pins.gpio1.into_analog(), Attenuation::Attenuation11dB);
        let mut pin2 = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB);
        let mut adc1 = ADC::<ADC1>::adc(analog.adc1, adc1_config).unwrap();
    
        let value1:u16 = adc1.read(&mut pin1).unwrap();
        let value2:u16 = adc1.read(&mut pin2).unwrap();
        println!("{}, {}",value1, value2);
    
[/code]

ジェネリクスに関する何かを私が勘違いしているのだと思うのですが、このエラーを回避するにはどうすればよいのでしょうか。

追記(23/07/12 14:00）：  
この問題の再現に必要なコードは以下のリポジトリ/ブランチに有ります。  
<https://github.com/elkel53930/micromouse-esp32/tree/stack_overflow>


CC BY-SA 4.0
2023-07-10T13:12:05.247
95552
2023-07-12T23:32:29.563
2023-07-12T05:05:36.137
59060
59060
question
rust esp32
esp-hal (Rust lang)で複数のADCポートを順に読み込む構造体を作りたい


>
> `OneShot`に与えているPINがPIN1なので、このエラーは当然かと思います。しかしpin1とpin2（つまり、gpio1とgpio2）では型が異なるため

> 一方で、構造体を使わずに以下のように書けばビルドエラーにはなりません。

`adc1`の具象型は問題なく、ジェネリクスにしたときだけ問題が起きるので、型パラメータ`SENADC`のトレイト境界に問題があると考えられます。

以下のように`SENADC`に`PIN2`に対する`OneShot`も追加したところ、コンパイルできるようになりました。

[code]

    impl<SENADC, PIN1, PIN2, ADCI> Sensors<SENADC, AdcPin<PIN1, ADCI>, AdcPin<PIN2, ADCI>>
        where
            SENADC: OneShot<ADCI, u16, AdcPin<PIN1, ADCI>> + OneShot<ADCI, u16, AdcPin<PIN2, ADCI>>,
            PIN1: Channel<ADCI, ID = u8>,
            PIN2: Channel<ADCI, ID = u8>,
            ADCI: RegisterAccess, {
    
[/code]


CC BY-SA 4.0
2023-07-12T23:32:29.563
95579
2023-07-12T23:32:29.563
14101
95552
answer