Skip to content
  • Категории
  • Главная
  • Документация
  • Последние
  • Пользователи
Collapse
  1. Главная
  2. Проекты
  3. Автоматизация, датчики, роботы
  4. Удаленное управление. I2C. Гироскоп.

Удаленное управление. I2C. Гироскоп.

Запланировано Прикреплена Закрыта Перенесена Автоматизация, датчики, роботы
1 Сообщения 1 Posters 61 Просмотры
  • Сначала старые
  • Сначала новые
  • По количеству голосов
Авторизуйтесь, чтобы ответить
Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
  • piP Не в сети
    piP Не в сети
    pi
    написал в отредактировано
    #1

    bddbe4c6-038d-4470-9cc5-e89aea4527db-image.png
    И снова здравствуйте.

    Раз уже сайт совсем умер, то напишу, пожалуй, ещё...А ну, как оживет.

    По случаю достал гироскоп на чипе L3G4200D, которым можно управлять как по I2C, так и по SPI. Даташит приводить на него, думаю, не стоит, потому как это легко гуглится. При помощи интерфейса i2c буду получить от него какие-нибудь сведения. Например значения по x, y и z. Что ж еще нужно от гироскопа?

    Сначала некоторые константы:

    адрес по-умолчанию = 0x69 (можно обнаружить прямо на малине при помощи, например i2cdetect)

    5 контрольных регистров 0x20..0x24

    Регистры значений X, Y, Z соответственно (0х28, 0х29), (0х2A, 0х2B), (0х2C, 0х2D). Значения занимают каждый по 2 байта в таком виде (Low, High).

    Lua:

    device_address	= 0x69
    ctrl_regs	= { 0x20, 0x21, 0x22, 0x23, 0x24 }
    
    R_xL = 0x28
    R_xH = 0x29
    
    R_yL = 0x2A
    R_yH = 0x2B
    
    R_zL = 0x2C
    R_zH = 0x2D
    

    Чтоб было интереснее сделаем метатаблицу lua для работы с данным чипом. Чтоб работать с гироскопом, как с отдельным объектом.

    i2c = fr.client.smbus -- псевдоним для клиента smbus
    
    -- пустая таблица без ничего.
    L3G4200D = { }
    
    -- метод new, который вернут новый экземпляр таблицы
    L3G4200D.new = function( ) 
        inst = { }
        for k, v in pairs(L3G4200D) do 
            inst[k] = v 
        end
        -- откроем девайс и сохраним его в нашей таблице.
        inst.i = assert(i2c.open( 1, device_address ))
        -- это метатаблица
        setmetatable( inst, L3G4200D )
        return inst
    end
    

    теперь можно сделать что-то типа

    local r = L3G4200D.new( )
    

    Код создаст экземпляр таблицы, откроет девайс и если все нормально, с ним можно работать.

    для того, чтоб настроить на работу устройство, добавлю функцию setup

    -- настройка состоит в том, чтоб записать нужные регистры нужными значениями. 
    L3G4200D.setup = function( self, scale ) 
        -- настроим таблицу. write_bytes ожидает таблицу, в которой указано [регистр]=значение
        local data = { 
    	[ctrl_regs[1]] = 15, -- включим
    	[ctrl_regs[2]] =  0, -- нормальный режим. По-умолчанию 
    	[ctrl_regs[3]] =  8, 
    	[ctrl_regs[4]] = scale_values[scale], -- установка scale
    	[ctrl_regs[5]] =  0 -- по-умолчанию
        }
        -- запишем. 
        assert(self.i:write_bytes(data))
    end
    

    Если не сработал assert, то гироскоп будет включен и готов к чтению данных. Функция для чтения тоже довольно проста

    -- табица для чтения. read_bytes ожидает в таблице номера регистров для чтения.
    read_xyz_data = { R_xL, R_xH, R_yL, R_yH, R_zL, R_zH }
    L3G4200D.read_xyz = function( self )
        -- читаем
        local res = assert(self.i:read_bytes( read_xyz_data ))
        -- возвращаем таблицу с уже поправленными значениями { x = ..,y = .., z = .. }
        return { x = res[R_xH] << 8 | res[R_xL],
                 y = res[R_yH] << 8 | res[R_yL],
                 z = res[R_zH] << 8 | res[R_zL] }
    end
    

    Теперь есть полный инструмент для получения данных с гироскопа. Далее я приведу скрипт, который раз в 100 миллисекунд вычитывает данные и выбрасывает их на консоль.

    i2c = fr.client.smbus
    eq  = fr.client.event_queue -- для работы с очередью событий клиента
    eqt = eq.timer  -- таймеры клиента
    
    device_address	= 0x69
    ctrl_regs	= { 0x20, 0x21, 0x22, 0x23, 0x24 }
    scale_values	= { [250]=0, [500]=16, [2000]=48 }
    
    R_xL = 0x28
    R_xH = 0x29
    
    R_yL = 0x2A
    R_yH = 0x2B
    
    R_zL = 0x2C
    R_zH = 0x2D
    
    read_xyz_data = { R_xL, R_xH, R_yL, R_yH, R_zL, R_zH }
    
    L3G4200D = { }
    
    L3G4200D.new = function( ) 
        inst = { }
        for k, v in pairs(L3G4200D) do 
            inst[k] = v 
        end
        inst.i = assert(i2c.open( 1, device_address ))
        setmetatable( inst, L3G4200D )
        return inst
    end
    
    L3G4200D.setup = function( self, scale ) 
        -- setup table for write
        local data = { 
    	[ctrl_regs[1]] = 15,
    	[ctrl_regs[2]] =  0,
    	[ctrl_regs[3]] =  8,
    	[ctrl_regs[4]] = scale_values[scale],
    	[ctrl_regs[5]] =  0 
        }
        -- write registry
        assert(self.i:write_bytes(data))
    end
    
    L3G4200D.read_xyz = function( self )
        local res = assert(self.i:read_bytes( read_xyz_data ))
        return { x = res[R_xH] << 8 | res[R_xL],
                 y = res[R_yH] << 8 | res[R_yL],
                 z = res[R_zH] << 8 | res[R_zL] }
    end
    
    -- функция таймера, которая вычитает данные и выведет их на консоль
    function show_values( err, dev ) -- первый параметр - ошибка таймера. при нормальной работе err=nil
        if nil == err then  
            local values = dev:read_xyz( ) -- вычитаем
    	print( "X:", values.x, 
                   "Y:", values.y, 
                   "Z:", values.z )        -- ... и выведем
    	eqt.post( show_values, {milli=100}, dev ) -- поставим новое задание в таймер на 100 milliсекунд
        else -- если ошибка 
    	fr.exit(err) -- завершимся. fr.exit( ) остановит очередь
        end
    end
     
    function main( )
        fr.run( ) -- запустим очередь событий
        local r = L3G4200D.new( ) -- откроем устройство
        r:setup(2000) -- настроем устройство
        show_values( nil, r ) -- запустим вывод.
    end
    

    теперь можно проверить: 192.168.1.3:12345 - адрес и порт агента на малине. Запущу и подвигаю железку немного.

    $ ./lua_client -s 192.168.1.3:12345 -e L3G4200D.lua 
    X:	129	Y:	500	Z:	65489
    X:	50	Y:	65468	Z:	65508
    X:	26	Y:	4	Z:	14
    ...............
    X:	34869	Y:	37125	Z:	21348
    X:	57781	Y:	65259	Z:	3636
    X:	32752	Y:	32752	Z:	32832
    ...............
    X:	76	Y:	78	Z:	23
    X:	73	Y:	7	Z:	11
    X:	78	Y:	62	Z:	65519
    X:	48	Y:	65495	Z:	45
    X:	14	Y:	4	Z:	6
    ^C
    

    На этом все, спасибо за внимание.

    PS: скрипт можно взять тут

    PPS: Добавил в пример получение значения температурного регистра: 0x26

    1 ответ Последний ответ
    0

    • Войти

    • Нет учётной записи? Зарегистрироваться

    • Login or register to search.
    • Первое сообщение
      Последнее сообщение
    0
    • Категории
    • Главная
    • Документация
    • Последние
    • Пользователи