Raspberry + Multiservo(Amperka)

Тема в разделе "Raspberry Pi", создана пользователем Igor68, 2 май 2016.

  1. Igor68

    Igor68 Гуру

    Доброго времени суток!
    Имеется RPi и Multiservo на 18 сервомашинок (от АМПЕРКА), но никак не могу наладить связь по i2c (не знаю как пакет управления передать - управлять). Интерфейс работает!

    команда i2cdetect -y 1 выдаёт:
    0 1 2 3 4 5 6 7 8 9 a b c d e f
    00: -- -- -- 06 07 -- -- -- -- -- -- -- --
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    40: -- -- -- -- -- -- -- 47 -- -- -- -- -- -- -- --
    50: 50 51 -- -- -- -- -- -- -- -- -- -- -- -- -- --
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    70: -- -- -- -- -- -- -- --

    где:
    06 07 - моя плата ComMotion motor driver - моя плата на 4 коллекторных двигателя (вчера с горем пополам до неё достучался и в BASH и в PYTHON)
    50 51 - просто так (для теста) подключил 24Cxx - не помню какая память (xx)
    47 - судя по скачанным проектам для multiservo - она и есть! (кстати всплывает не всегда - судя по документации i2c на этой плате работает с интервалом)

    Собственно вопрос - какой протокол обмена, ну или пример обмена по i2c.
    Спасибо!
     
  2. ANV

    ANV Гуру

  3. Igor68

    Igor68 Гуру

    Уже часа 4 курю эти исходники! Одно смущает:
    #include <Arduino.h>

    #include <Wire.h>

    ведь там определено (Wire):
    do {
    Wire.beginTransmission(twiAddress);
    Wire.write(pin);
    Wire.write(pulseWidth >> 8);
    Wire.write(pulseWidth & 0xFF);
    errorCode = (Error)Wire.endTransmission();
    } while (errorCode && --retryAttempts);

    Wire.beginTransmission(twiAddress);
    - опнятно, что адрес!
    а вот к примеру Wire.write(pin); установка просто на i2c или запись по какому-то адресу внутри устройства.
    Как пример (беру из PYTHON):
    write_byte(addr, p0) - передаём по адресу i2c addr параметр p0
    write_byte_data(addr, saddr, p0) - передаём по адресу i2c addr в регистр saddr параметр p0
    вчера с ComMotion получилось (не без описания) получилось по write_byte_data(addr, saddr, p0)
    пока не компилю на си - очень неудобно удаленно на Raspberry и тут же пробовать, пока пробую на интерпретаторах (PYTHON, BASH). Отработаю - тогда уж и мой любимый GCC.
    Организовал RAM-disk на Raspberry в нём и кручу всё это и тут же запускаю. С утра ковыряюсь с Multiservo, с ComMotion вчера быстрее получилось. Устал уж от того и болтаю много. Но спасибо, что откликнулись.
     
  4. ANV

    ANV Гуру

    Попробуйте write_word_data(twiAddress, pin, val)
     
  5. Igor68

    Igor68 Гуру

    write_word_data(twiAddress, pin, val)
    в данном случае twiAddress - адрес на шине i2c, pin - адрес регистра внутри устройства на шине i2c, val - 8-ми битное значение (байт), но в исходнике 490 <= val <= 2400, т.е. двухвайтоное значение:
    write_word_data(twiAddress, pin, val(l/h))
    write_word_data(twiAddress, pin + 1, val(h/i))

    К сожалению не работает. Эту команду уже применял ранее. Пока не разберусь сколько, чего и куда отправить, чтоб сервромашина заработала. Судя по всему плата исправна, коли связь есть и при подачи питания сервомашины (их 2 шт) вжыкают.
     
    Последнее редактирование: 3 май 2016
  6. Igor68

    Igor68 Гуру

    Понимаю так, что никто не использует эти шилды в составе Raspberry Pi а только через Arduino и зря маюсь с этим - деньги на ветер?
     
    Последнее редактирование: 3 май 2016
  7. ANV

    ANV Гуру

    Функция write_word_data отсылает слово, т.е. val двухбайтный.

    Конструкция:
    write_word_data(twiAddress, pin, val(l/h))
    write_word_data(twiAddress, pin + 1, val(h/i))

    В корне неверная. Вас сбила с толку "высокоуровневая обертка", которую прикрутили на питоне для i2c. Она заключается в том, что большинство i2c микросхем содержат регистры. В шилд надо послать i2c_addr, pin, us_high, us_low, поэтому надо использовать write_word_data(twiAddress, pin, val). Если разбить как вы указали, то будут посланы команды для двух разных пинов с некорректными значениями

    В чем я вижу тут могут быть еще проблемы:
    1. Возможно в val надо будет поменять местами старший и младший байт, т.к. непонятно какой уходит первым. Правильно посылать первым старший
    2. В исходниках Амперки почему-то эти данные отправляются несколько раз. Возможно это "фича" платы, что с первого раза может не принять и поэтому требуется 5 попыток.

    Отставить панику, все заработает :)
     
    Igor68 нравится это.
  8. Igor68

    Igor68 Гуру

    Простите, что обманываю с write_word_data(twiAddress, pin, val(l/h)) невнимательность!
    я применял write_byte_data(twiAddress, pin, val(l/h)) потому и писал про байты.
    Сейчас попробую.

    и ещё - если я правильно понял не надо обращаться по адресу, а просто посылать пакет в определённом формате - так?
     
    Последнее редактирование: 4 май 2016
  9. Igor68

    Igor68 Гуру

    Заработало!
    Если кому интересно:
    Код (Python):

    #!/usr/bin/python
    # coding: utf-8

    import smbus
    import time

    print("=====test multiservo=====")

    addr = 0x47

    bus = smbus.SMBus(1)

    pin = 1
    res = 0

    set = 700

    def wrmultiservo(addr, _pin, val):
       global res
       res = 0
       tm = 0.05
       te = 1
       p0 = (val >> 8)
       p1 = val & 0xff
       cmd = _pin
       try:
         print(addr, cmd, p0, p1)
         bus.write_i2c_block_data(addr, cmd, [p0, p1])
         time.sleep(tm)
         res = 1;
       except:
         print("--error--")
         time.sleep(tm)

    def sup(pin):
       global set
       global addr
       global res
       while(set < 1700):
         wrmultiservo(addr, pin, set)
         if(res > 0):
           res = 0
           set = set + 10
    #
    def sdown(pin):
       global set
      global addr
       global res
      while(set > 700):
      wrmultiservo(addr, pin, set)
      if(res > 0):
      res = 0
      set = set - 10
    #
    nums=10
    while(nums > 0):
       sup(pin)
       sdown(pin)
       nums = nums - 1
     
    В процессе опытов убил одну сервомашину - по своей глупости.
    Моя глупость:
    Подключение было вместе с ComMotion motor driver. Смонтировано в виде бутерброда, и питание от него. Но не учёл, что этот самый ComMotion время от времени начинает откликаться на все адреса I2C. Ну соответственно и с ним произошло что-то тоже, а стали работать только два его двигателя, причём один работает только в одну сторону.

    так что у меня заработала только write_i2c_block_data(addr, cmd, [p0, p1]) другие более не стал трогать.
     
    mshock нравится это.