Особенности сигнала зажигания IG- в диагностическом разъеме двигателя 5S-FE

Стало любопытно собрать стробоскоп для диагностики угла опережения зажигания. Изначально хотелось взять сигнал IG- с диагностического разъема, да зажигать по нему мощный светодиод.
А вот и не угадал. Осциллограмма этого сигнала рядом с сигналом, снятым с высоковольтных проводов представлена ниже.

Первый канала (зеленый) — ноги IG-, второй (желтый) — сигнал с высоковольтных проводов. Первый канал имеет масштаб 10 вольт на деление (снимался со щупом 1/10), второй — 5 вольт на деление.
Как видим, форма сигнала IG- весьма любопытна. В принципе, моменты зажигания свечи и начала высокого пика зажигания совпадают, правда использовать его для синхронизации становится не так просто.

осциллограмма зажигания

Подключение экрана Nokia 1202 к аппаратному SPI контроллера STM32F0

Для любителей микроконтроллеров экраны от старых телефонов Nokia давно стали одним из основных устройств вывода простой, но уже графической информации.
Вот и у меня возник проект, который уже давно тесно связан с подключением какого-нибудь небольшого LCD экрана к микроконтроллеру.
Изначально проект планировалось делать на процессорах ATMega48. Но когда я уже решил, что хватит заниматься проектированием, надо брать макетки и начинать что-то собирать — мне посоветовали посмотреть в сторону STM32. Довольно приятный сюрприз, что полноценная отладочная плата с JTAG на борту стоит всего 500 рублей. Таки был приобретен STM32F0 Discovery.
На борту у него стоит чип STM32F051R8. Применительно к данной статье у него есть отличный плюс — он позволяет изменять ширину слова, передаваемого по шине SPI.
Убедившись, что экран от Nokia 1202 неплохо работает в программном режиме передачи данных, выдавая вполне неплохие 70 кадров в секунду на перерисовку всего экрана, я все же озадачился использованием аппаратных возможностей микроконтроллера для передачи данных в сторону экрана.

Подключение к SPI2
Так ка SPI1 гораздо мощнее, чем SPI2, а мощностей посленего более чем достаточно для подключения LCD экрана, то будем использовать именно его.
Согласно документации, ноги MOSI и SCK располагаются на выводах PB15 и PB13 соответственно. ПО соседству, на отладочной плате располагаются ноги PC6 и PC7. Их мы будем использовать для передачи сигналов CS и RESET соответственно. Можно было бы, конечно, воспользоваться PB14, т.к. он мультиплексируется с MISO, не используемым в данном случае, но мне очень не хотелось менять порядок ног при напаивании на макетку. Да, грешен, разъемов у меня нет, и обжимать лень.

Настройка ног RESET и CS ничем не отличается от обычного программного режима:

/* Configure GPIO for CS/RST pins */
RCC_AHBPeriphClockCmd(LCD_GPIO_RCC, ENABLE);
GPIO_init_str.GPIO_Pin = LCD_RESET_PIN | LCD_CS_PIN;
GPIO_init_str.GPIO_Mode = GPIO_Mode_OUT;
GPIO_init_str.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LCD_GPIO, &GPIO_init_str);
GPIO_WriteBit(LCD_GPIO, LCD_RESET_PIN, Bit_SET); // Поднимаем ногу RESET в состояние логической единицы
GPIO_WriteBit(LCD_GPIO, LCD_CS_PIN, Bit_RESET); // А ногу CS в противоположность, опускаем

Как вы можете заметить, нога CS изначально опускается в состояние логического нуля. Объясняется это оптимизацией производительности — контроллер LCD будет работать и без постоянного изменения состояния CS, однако, это позволит нам сэкономить время. Опытным путем было выяснено, что после опускания ноги CS при работе аппаратного SPI потребуется довольно внушительная пауза, негативно влияющая на производительность.

Для того, чтобы настроить SPI, в первую очередь следует связать ноги PB13 и PB15 с этим самым SPI:

/* Configure GPIOB for SDA/CLK pins */
RCC_AHBPeriphClockCmd(LCD_SPI_GPIO_RCC, ENABLE);
GPIO_PinAFConfig(LCD_SPI_GPIO, LCD_SDA_PIN_SOURCE, GPIO_AF_0);
GPIO_PinAFConfig(LCD_SPI_GPIO, LCD_SCK_PIN_SOURCE, GPIO_AF_0);

А затем настроить PB13 и PB15 на использование альтернативной функции:

/* Configure GPIO pins for SPI */
GPIO_init_str.GPIO_Pin = LCD_SDA_PIN | LCD_SCK_PIN;
GPIO_init_str.GPIO_Mode = GPIO_Mode_AF;
GPIO_init_str.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_init_str.GPIO_OType = GPIO_OType_PP;
GPIO_init_str.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(LCD_SPI_GPIO, &GPIO_init_str);

Немного расскажу о настройке SPI. Семейство экранов, в которые входит в том числе используемый автором данной статьи экран Nokia 1202 используют полудуплексный 9-битный serial interface. Сигнально он полностью совместим с SPI. Однако, не каждый микроконтроллер умеет хитрость с дополнительным битом, который определяет, что сейчас собираются передать контроллеру экрана — данные, или команду.
Поэтому, основные настройки выглядят следующим образом:

SPI_init_str.SPI_Direction = SPI_Direction_1Line_Tx; // Полудуплексный режим, включена только передача со стороны микроконтроллера
SPI_init_str.SPI_Mode = SPI_Mode_Master; //Микроконтроллер является мастером соединения
SPI_init_str.SPI_DataSize = SPI_DataSize_9b; //Режим слова - 9 бит
SPI_init_str.SPI_CPOL = SPI_CPOL_High; //Сигнал Clock в режиме простоя находится в в состоянии логической единицы
SPI_init_str.SPI_CPHA = SPI_CPHA_2Edge; //Передача данных осуществляется по правому краю сигнала Clock, т.е. в момент подъема из 0 в 1
SPI_init_str.SPI_NSS = SPI_NSS_Soft; //Отключаем аппаратное управление CS
SPI_init_str.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //Устанавливаем скорость передачи данных. SPI тактируется от fPCLK.
SPI_init_str.SPI_FirstBit = SPI_FirstBit_MSB; //При передаче слова первым идет наиболее значимый бит (MSB)
SPI_Init(LCD_SPI, &SPI_init_str);

Далее необходимо сообщить ядру SPI состояние ноги NSS (мы же выключили аппаратное управление):

SPI_NSSInternalSoftwareConfig(LCD_SPI, SPI_NSSInternalSoft_Set);

Если этого не сделать, то SPI будет считать, что шина уже занята и ничего передавать не будет.

Ну и финальный аккорд — включаем SPI:

SPI_Cmd(LCD_SPI, ENABLE);

Далее идут уже знакомые процедуры сброса и инициализации экрана.

Передача данных
Для того, чтобы полностью раскрыть возможности аппаратного блока SPI следует передавать данные пачками.
Иначе говоря, следует отказаться от подхода 1 вызов — один байт, а передавать указатель на последовательность данных.
Основное преимущество в данном случае заключается в том, что мы можем поддерживать буфер FIFO шины SPI полным, выжимая максимум скорости передачи.
Выглядит это следующим образом:

void lcd_write(char cd, const char * data, unsigned short int len, unsigned short int repeat)
{
char i;

while(repeat > 0)
{
for(i = 0; i < len; i++)
{
unsigned short int octet = data[i];
if (cd) octet |= 0x100;
SPI_I2S_SendData16(SPI2, octet);
while (SPI_GetTransmissionFIFOStatus(SPI2) == SPI_TransmissionFIFOStatus_Full); //Wait, if SPI FIFO is full
}
repeat --;
}
while (SPI_GetTransmissionFIFOStatus(SPI2) != SPI_TransmissionFIFOStatus_Empty); //Wait, while SPI FIFO not empty
}

Вы можете заметить также полезный параметр - repeat. Это позволяет однотипно закрашивать области в одной транзакции.

На этом, пожалуй, особенности использования аппаратного блока SPI заканчиваются. Результатом стал десятикратный прирост производительности с 70 кадров в секунду до 700 при закрашивании всего экрана.

Исходные коды библиотеки и демонстрационной программы можно взять здесь: lcd1202.zip

Множественный AuthBasicProvider в Apache mod_auth_basic

Захотелось мне, чтобы апач аутентифицировал пользователей одновременно в htpasswd и в ldap, равноценно, вне зависимости от того, удалось ли ему авторизовать пользователя другим способом.
Казалось бы — вот они, канонические примеры, взятые с официальной документации:


AuthName "Private"
AuthType Basic
AuthBasicProvider file ldap
AuthUserFile /usr/local/apache/passwd/passwords
AuthLDAPURL ldap://ldaphost/o=yourorg
Require valid-user

Все хорошо до тех пор, пока нам не потребуется, чтобы пользователь успешно аутентифицировался в ldap, даже если его имя уже найдено в file и пароль не подошел.

Казалось бы — у ldap есть отличный параметр: AuthzLDAPAuthoritative
Давайте ldap будет первым, и не будет авторитетным.


AuthBasicProvider ldap file
AuthzLDAPAuthoritative Off

Работает? Нет. По логике совершенно непонятно, почему. Ведь ldap — не авторитет.
Оказывается, есть еще один параметр: AuthLDAPBindAuthoritative
И именно он определяет, будет ли процесс аутентификации/авторизации передан следующему модулю в случае, если объект для данного пользователя будет найден, но bind не будет успешен.
Таким образом, следует использовать такие параметры:


AuthName "Private"
AuthType Basic
AuthBasicProvider ldap file
AuthzLDAPAuthoritative Off
AuthLDAPBindAuthoritative Off
AuthUserFile /usr/local/apache/passwd/passwords
AuthLDAPURL ldap://ldaphost/o=yourorg
Require valid-user

Шрифты в Debian Squeeze

Весьма избитая тема, конечно. Однако, в большинстве инструкций все упирается в давно просроченные ссылки, и найти один из патчей было не так-то просто.

Для того, чтобы не заниматься ручной настройкой шрифтов, не искать нужные настроечные файлы для /etc/fonts, будем патчить не только cairo, но и fontconfig. Разбираться, какие патчи для fontconfig из пакета ubuntu нужны, а какие нет — было лень, поэтому я использовал все.

Подготовка к сборке:
apt-get install dpkg-dev devscripts

Исходный код:
apt-get source libcairo2 fontconfig

Зависимости для сборки:
apt-get build-dep libcairo2 fontconfig

Далее необходимо стянуть патчи:
wget http://randoman.ru/files/squeeze-fonts/squeeze-fonts-patches.tar.gz
tar -zxf squeeze-fonts-patches.tar.gz

Накладываем патчи на cairo:
cd cairo-1.8.10
patch -p1 -i ../squeeze-fonts-patches/cairo/04_lcd_filter.patch
patch -p1 -i ../squeeze-fonts-patches/cairo/06_Xlib-Xcb-Hand-off-EXTEND_PAD-to-XRender.patch
patch -p1 -i ../squeeze-fonts-patches/cairo/cairo-respect-fontconfig.patch

Обновляем версию:
dch -i
Что-нибудь пишем после звездочки, сохраняем, выходим.

Собираем пакет:
dpkg-buildpackage

Накладываем патчи на fontconfig:
cd ../fontconfig-2.8.0/
patch -p1 -i ../squeeze-fonts-patches/fontconfig/00_old_diff_gz.patch
patch -p1 -i ../squeeze-fonts-patches/fontconfig/04_ubuntu_monospace_lcd_filter_conf.patch
patch -p1 -i ../squeeze-fonts-patches/fontconfig/05_lcdfilterlegacy.patch
patch -p1 -i ../squeeze-fonts-patches/fontconfig/05_ubuntu_add_hinting_and_antialiasing_confs.patch
patch -p1 -i ../squeeze-fonts-patches/fontconfig/06_ubuntu_lcddefault.patch
patch -p1 -i ../squeeze-fonts-patches/fontconfig/07_no_bitmaps.patch

Обновляем версию:
dch -i
Также что-нибудь пишем после звездочки, сохраняем, выходим.

Собираем пакет:
dpkg-buildpackage

Устанавливаем пакеты:
cd ..

Для 32-битных систем:
dpkg -i fontconfig_2.8.0-2.2_i386.deb fontconfig-config_2.8.0-2.2_all.deb libcairo2_1.8.10-6.1_i386.deb libfontconfig1_2.8.0-2.2_i386.deb

Для 64-битных систем:
dpkg -i fontconfig_2.8.0-2.2_amd64.deb fontconfig-config_2.8.0-2.2_all.deb libcairo2_1.8.10-6.1_amd64.deb libfontconfig1_2.8.0-2.2_amd64.deb

Если необходимо — установить dev пакеты.

После этого надо перезапустить иксы. Ну или просто перезагрузиться.

Велосвет

Наконец-то сделали велосвет. Светит вот так:

Светодиоды: CREE XP-E (4500K)
Стабилизаторы: zxsc400
Ток на диодах 420mA, КПД точно не мерялся, но навскидку мало отличается от 90-95%.
Питание от 800-граммовой свинцовой батареи 4.5Ah 6V

Hint: снималось таким образом, чтобы видимое на экране фотоаппарата соответствовало видимому живую. Ощущения могут зависеть от яркости вашего монитора ;)

Защищено: Toyota Corolla FX

Эта запись защищена паролем. Для её просмотра введите, пожалуйста, пароль:

Новые фары

Т.к. выпиливал из уже немного поврежденного уголка, вышло с косячками :)

Проблема с зеркалированием

Выяснилось, что если apr-mirror некрасиво оборвать (причин тому может быть множество), то в дальнейшем его запуск окажется невозможным без вмешательства. Виной тому вот это творчество:

sub lock_aptmirror {
system ("touch " . get_variable("var_path") . "/apt-mirror.lock");
}

Ни тебе расположения в заведомо очищаемых при загрузке директориях, ни тебе flock().
Как следствие — «протухшее» на несколько дней зеркало. Приношу извинения всем, кто пользуется зеркалом.

Нашли маленькую кошечку. Теперь у нас двое кошачьих :)

За 3 часа до наступления 2011 года подобрали в подъезде чудную белую кошечку :)