вторник, 30 сентября 2014 г.

usb светофор.

Готовые программные библиотеки такие как например libusb (для ПК) и v-usb (для микроконтроллера) значительно упрощают создание связи ПК c микроконтроллером через usb. Пример с включением светодиода через usb(скачиваемый вместе с библиотекой v-usb) очень полезен. В этом примере, несмотря на то что включается один светодиод, размер передаваемой (для дальнейшего свободного использования) информации больше одного бита, рассмотрим часть кода из примера:

/* ------------------------------------------------------------------------- */

usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t    *rq = (void *)data;

    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_VENDOR){
        DBG1(0x50, &rq->bRequest, 1);   /* debug output: print our request */
        if(rq->bRequest == CUSTOM_RQ_SET_STATUS){
            if(rq->wValue.bytes[0] & 1){    /* set LED */
                LED_PORT_OUTPUT |= _BV(LED_BIT);
            }else{                          /* clear LED */
                LED_PORT_OUTPUT &= ~_BV(LED_BIT);
            }
        }else if(rq->bRequest == CUSTOM_RQ_GET_STATUS){
            static uchar dataBuffer[1];     /* buffer must stay valid when usbFunctionSetup returns */
            dataBuffer[0] = ((LED_PORT_OUTPUT & _BV(LED_BIT)) != 0);
            usbMsgPtr = dataBuffer;         /* tell the driver which data to return */
            return 1;                       /* tell the driver to send 1 byte */
        }
    }else{
        /* calss requests USBRQ_HID_GET_REPORT and USBRQ_HID_SET_REPORT are
         * not implemented since we never call them. The operating system
         * won't call them either because our descriptor defines no meaning.
         */
    }
    return 0;   /* default for not implemented requests: return no data back to host */
}

/* ------------------------------------------------------------------------- */


Даже если код непонятен можно догадаться где и как используется принятая информация. В строке:
 if(rq->wValue.bytes[0] & 1){     /* set LED */
Определяется равен ли единице первый бит первого байта информации (для свободного использования) принятой микроконтроллером от компьютера. По аналогии можно написать код для определения второго бита первого байта принятой информации:
 if(rq->wValue.bytes[0] &  2){  }
Для третьего бита первого байта:
 if(rq->wValue.bytes[0] & 4){  }
Для 4го бита первого байта:
 if(rq->wValue.bytes[0] & 8){  }
и т.д. до 8го бита т.к. в 1ом байте 8бит. Если принято больше 1го байта то код для определения первого бита второго байта будет выглядеть так:
 if(rq->wValue.bytes[1] & 1){  }
второго бита второго байта:
 if(rq->wValue.bytes[1] & 2){  }
и т.д. по аналогии с первым байтом. Т.о. можно принимать много информации. Например если передаётся одно число типа int то минимум будет передано 2 байта (но скорее всего 4), если тип long то м.б. 4 байта (или 8), передавать можно не только числа но и массивы и другие типы данных. Если надо управлять 4мя светодиодами то можно использовать например такую схему:
Рисунок 1 - usb светофор

Для управления всеми светодиодами достаточно 4 бита (или пол байта). Измененный код для схемы на рисунке 1:

#define LED_PORT_DDR        DDRB
#define LED_PORT_OUTPUT     PORTB
#define LED_BIT             1
#define LED_BIT2            2
#define LED_BIT3            3
#define LED_BIT4            4

#define LED_BIT_MASK             1 //в двоичной = 1
#define LED_BIT_MASK2            2 //в двоичной = 10
#define LED_BIT_MASK3            4 //в двоичной = 100
#define LED_BIT_MASK4            8 //в двоичной = 1000

#define F_CPU 12000000UL  // 12 MHz

#include "avr/io.h"
#include "avr/wdt.h"
#include "avr/interrupt.h"  /* for sei() */
#include "util/delay.h"     /* for _delay_ms() */

#include "avr/pgmspace.h"   /* required by usbdrv.h */
#include "usbdrv.h"
#include "oddebug.h"        /* This is also an example for using debug macros */
#include "requests.h"       /* The custom request numbers we use */

/* ------------------------------------------------------------------------- */
/* ----------------------------- USB interface ----------------------------- */
/* ------------------------------------------------------------------------- */

PROGMEM const char usbHidReportDescriptor[22] = {   /* USB report descriptor */
    0x06, 0x00, 0xff,              // USAGE_PAGE (Generic Desktop)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x09, 0x00,                    //   USAGE (Undefined)
    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)
    0xc0                           // END_COLLECTION
};
/* The descriptor above is a dummy only, it silences the drivers. The report
 * it describes consists of one byte of undefined data.
 * We don't transfer our data through HID reports, we use custom requests
 * instead.
 */

/* ------------------------------------------------------------------------- */

usbMsgLen_t usbFunctionSetup(uchar data[8])
{
usbRequest_t    *rq = (void *)data;

    if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_VENDOR){
        DBG1(0x50, rq->bRequest, 1);   /* debug output: print our request */
        if(rq->bRequest == CUSTOM_RQ_SET_STATUS){
            if(rq->wValue.bytes[0] & 1){    /* set LED */
                LED_PORT_OUTPUT |= _BV(LED_BIT);
            }else{                          /* clear LED */
                LED_PORT_OUTPUT &= ~_BV(LED_BIT);
            }

if(rq->wValue.bytes[0] & LED_BIT_MASK2){    /* set LED2 */
                LED_PORT_OUTPUT |= _BV(LED_BIT2);
            }else{                          /* clear LED2 */
                LED_PORT_OUTPUT &= ~_BV(LED_BIT2);
            }
if(rq->wValue.bytes[0] & LED_BIT_MASK3){    /* set LED3 */
                LED_PORT_OUTPUT |= _BV(LED_BIT3);
            }else{                          /* clear LED3 */
                LED_PORT_OUTPUT &= ~_BV(LED_BIT3);
            }
if(rq->wValue.bytes[0] & LED_BIT_MASK4){    /* set LED4 */
                LED_PORT_OUTPUT |= _BV(LED_BIT4);
            }else{                          /* clear LED4 */
                LED_PORT_OUTPUT &= ~_BV(LED_BIT4);
            }

//if(rq-->wValue.bytes[0] & LED_BIT_MASK){ //в двоичной 1
            //    LED_PORT_OUTPUT |= _BV(LED_BIT);
            //}else{                        
            //    LED_PORT_OUTPUT &= ~_BV(LED_BIT);
            //}
//if(rq->wValue.bytes[1] & LED_BIT_MASK){ //в двоичной 1 0000 0000
            //    LED_PORT_OUTPUT |= _BV(LED_BIT);
            //}else{                        
            //    LED_PORT_OUTPUT &= ~_BV(LED_BIT);
            //}

        }else if(rq->bRequest == CUSTOM_RQ_GET_STATUS){
            static uchar dataBuffer[1];     /* buffer must stay valid when usbFunctionSetup returns */
            dataBuffer[0] = ((LED_PORT_OUTPUT & _BV(LED_BIT)) != 0);
            usbMsgPtr = dataBuffer;         /* tell the driver which data to return */
            return 1;                       /* tell the driver to send 1 byte */
        }
    }else{
        /* calss requests USBRQ_HID_GET_REPORT and USBRQ_HID_SET_REPORT are
         * not implemented since we never call them. The operating system
         * won't call them either because our descriptor defines no meaning.
         */
    }
    return 0;   /* default for not implemented requests: return no data back to host */
}

/* ------------------------------------------------------------------------- */

int __attribute__((noreturn)) main(void)
{
uchar   i;

    wdt_enable(WDTO_1S);
    /* Even if you don't use the watchdog, turn it off here. On newer devices,
     * the status of the watchdog (on/off, period) is PRESERVED OVER RESET!
     */
    /* RESET status: all port bits are inputs without pull-up.
     * That's the way we need D+ and D-. Therefore we don't need any
     * additional hardware initialization.
     */
    odDebugInit();
    DBG1(0x00, 0, 0);       /* debug output: main starts */
    usbInit();
    usbDeviceDisconnect();  /* enforce re-enumeration, do this while interrupts are disabled! */
    i = 0;
    while(--i){             /* fake USB disconnect for > 250 ms */
        wdt_reset();
        _delay_ms(1);
    }
    usbDeviceConnect();
    LED_PORT_DDR |= _BV(LED_BIT);   /* make the LED bit an output */

LED_PORT_DDR |= _BV(LED_BIT2);   /* make the LED2 bit an output */
LED_PORT_DDR |= _BV(LED_BIT3);   /* make the LED3 bit an output */
LED_PORT_DDR |= _BV(LED_BIT4);   /* make the LED4 bit an output */


    sei();
    DBG1(0x01, 0, 0);       /* debug output: main loop starts */
    for(;;){                /* main event loop */
#if 0   /* this is a bit too aggressive for a debug output */
        DBG2(0x02, 0, 0);   /* debug output: main loop iterates */
#endif
        wdt_reset();
        usbPoll();
    }
}

/* ------------------------------------------------------------------------- */

Также необходимо не забыть про инициализацию портов. Если программа записывается в микроконтроллер через spi то во время записи нужно чтобы светодиоды VD5 и VD6 были отсоединены от выводов микроконтроллера иначе возможно что эти светодиоды помешают нормальной записи. Код (текст в файле файл set-led.c) можно скачать с Яндекс диска.

Остальные файлы без изменений, компилируются проекты также (командой make hex для микроконтроллера, командой make для ПК).


КАРТА БЛОГА (содержание)

суббота, 27 сентября 2014 г.

Включение светодиода через usb.

Для реализация управления устройствами через usb-порт потребуется намного больше действий чем для реализации управления через lpt-порт, тем не менее управление через usb имеет преимущества перед управлением через lpt. Рассмотрим схему:
Рисунок 1 - Включение светодиода через usb

Для связи с usb-портом используется микроконтроллер ATmega8A-PU но можно использовать и ATtiny2313 и любой другой AVR микроконтроллер способный работать на частоте 12МГц и имеющий как минимум 2кб flash памяти. ATtiny2313 имеет 2кб flash памяти но помимо связи с usb микроконтроллер также должен заниматься выполнением некоторых других задач поэтому для связи с usb выбран ATmega8A-PU имеющий 8кб flash памяти. Диоды VD1 и VD2 нужны для согласования уровней напряжения для "общения" с usb, эти диоды понижают напряжение питания и следовательно напряжения на выводах микроконтроллера. Есть схемы в которых для согласования уровней используются стабилитроны. Со стабилитронами могут быть проблемы из за которых устройство может не распознаваться. Стабилитроны должны быть маломощными и может понадобиться подбор резисторов. Поэтому для избежания проблем используется схема с понижением напряжения питания. Важно правильно собрать схему, при сборке не делать слишком длинных путей прохождения тока, слишком широких пересечений проводников, ничего лишнего не замкнуть и не перепутать подключение.
Для написания программы для микроконтроллера понадобится библиотека v-usb последнюю и самую актуальную версию которой можно скачать с официального сайта http://www.obdev.at/products/vusb/download.html. В скачанном v-usb архиве будет папка "examples" в ней будет пример "hid-custom-rq" который (с небольшими переделками) и будет использоваться для включения светодиода через usb. Для компиляции данного примера понадобится скачать и установить:
WinAVR (для компиляции примера для микроконтроллера),
MinGW-5.1.4.exe (для компиляции примера для микроконтроллера).
Которые для простоты дальнейших действий лучше установить туда куда предлагается по умолчанию, более подробно об установке этих программ на сайте: microsin.net. После установки MinGW-5.1.4.exe в переменную Path необходимо прописать путь c:\MinGW\bin\ на сайте microsin.net об этом написано но важно при прописывании этого пути не удалить другие, данный путь дописывается в конец после точки с запятой которую необходимо дописать если её нет. В windows7 чтобы изменить переменную Path:
1) Правой кнопкой мыши нажимается на значок "Компьютер" (или "мой компьютер"),
2) Выбирается "Свойства",
3) Выбирается "Дополнительные параметры системы",
4) Нажимается на кнопке "Переменные среды...",
5) В поле "Системные переменные" выбирается "Path" нажимается кнопка "Изменить...",
6) В поле "Значение переменной:" дописывается ";c:\MinGW\bin\" (или туда где MinGW установлена если не по умолчанию).
В распакованной папке v-usb лучше ничего не перемещать и не копировать а изменения производить в самом примере (если что можно скачать заново). в папке "hid-custom-rq" есть папка "firmware" в этой папке есть файл "Make" его надо открыть через какой нибудь текстовый редактор и найти строки:
DEVICE  = atmega168
F_CPU   = 16000000 # in Hz
и заменить на:
DEVICE  = atmega8
F_CPU   = 12000000 # in Hz
Если кварцевый резонатор на другую частоту и/или микроконтроллер другой то заменить на то что есть на самом деле. Если дополнительные действия с папками и файлами в этой скачанной v-usb папке не проводилось и записывать программу в микроконтроллер через этот Make файл не планируется то далее ничего можно не менять, этот файл сохраняется и закрывается.
В файле usbconfig
Необходимо убедится в том что есть такие записи:
#define USB_CFG_IOPORTNAME      D
#define USB_CFG_DMINUS_BIT      4
#define USB_CFG_DPLUS_BIT       2
#define USB_CFG_INTERFACE_CLASS     3
Можно изменить VENDOR_NAME и DEVICE_NAME:
#define USB_CFG_VENDOR_NAME     'e','l','e','c','t','e','.','b','l','o','g','s','p','o','t','.','c','o','m'
#define USB_CFG_VENDOR_NAME_LEN 19
#define USB_CFG_DEVICE_NAME     'm','y','u','s','b','d','e','v','i','c','e'
#define USB_CFG_DEVICE_NAME_LEN 11

В файле main находим строку:
#define LED_BIT             0
и меняем на:
#define LED_BIT             1
т.к. светодиод подключен к первому биту порта B, если сразу подключить его к биту 0 то эту строку менять не надо, можно подключить к другому биту порта B и внести соответствующие изменения в эту строку.
На всякий случай дописываем строку:
#define F_CPU 12000000UL  // 12 MHz
Сохраняем и закрываем.
Файл "requests" менять не надо.
Далее открываем cmd (командная строка) и переходим в этой командной строке в папку "firmware", если например папка v-usb находиться на диске d то сделать это можно 3мя командами: 
cd c:\
d:
cd d:\vusb-20121206\examples\hid-custom-rq\firmware\
Далее для того чтобы откомпилировать пример вводится команда:
make hex
Если компиляция прошла успешно то в папке "firmware" должен появиться файл "main.hex", его нужно прошить в микроконтроллер. Если используется программатор stk200 (5 проводков), lpt порт, микроконтроллер m8, частота кварцевого резонатора 12МГц, файл "main.hex" скопирован в корень диска C, на компьютере имеется утилита avrdude которая устанавливается вместе с WinAVR то для прошивки файла "main.hex" в микроконтроллер в командной строке достаточно выполнить две команды:
cd C:\
avrdude -c stk200 -P lpt1 -p m8 -U lfuse:w:0x9f:m -U hfuse:w:0xc9:m -U flash:w:main.hex
Обратите внимание на "-U lfuse:w:0x9f:m -U hfuse:w:0xc9:m" -это установка фьюзов если их неправильно установить то можно испортить микроконтроллер. Для правильной установки фьюзов может пригодится калькулятор фьюзов http://fusecalc.mirmk.net/. Для того чтобы команда в командной строке выполнилась необходимо вписать эту команду в чёрное текстовое поле командной строки и нажать клавишу "Enter" на клавиатуре компьютера в котором открыта эта командная строка. Для того чтобы hex-файл записался (прошился) в микроконтроллер необходимо чтобы в момент когда компьютер выполняет запись этой прошивки в микроконтроллер к этому компьютеру был подключён программатор к которому подключён микроконтроллер иначе прошить микроконтроллер не получиться. Если программатор stk200 (5 проводков) то на микроконтроллер в момент прошивки должно быть подано питание, питание следует подавать только после подключения программатора к компьютеру и отключать только перед выниманием из компьютера иначе можно испортить порт или микроконтроллер. Если прошивка прошла успешно то можно воткнуть устройство в usb порт и посмотреть в диспетчере устройств распозналось ли устройство или нет. Если в диспетчере устройств написано "неизвестное устройство" или что то вроде этого то устройство не распозналось и необходимо искать причину и устранять её, если в диспетчере устройств появилась строка где написано "HID-устройство","usb устройство ввода" или что то в этом роде то устройство распозналось.
Для организации "общения" компьютера с микроконтроллером используя скачанный пример необходимо скачать и установить библиотеку libusb (libusb-win32-releases) при установке  устройство должно быть подключено к компьютеру для того чтобы заодно установился драйвер фильтра. Подробнее про установку libusb на сайте: microsin.net. В папке "commandline" (которая находится там же где и папка "firmware") есть файл "Make" его надо открыть и найти в нём строки:
USBFLAGS = `libusb-config --cflags`
USBLIBS = `libusb-config --libs`
и закомментировать:
USBFLAGS = `libusb-config --cflags`
USBLIBS = `libusb-config --libs`
найти строки:
USBFLAGS = -I/usr/local/include
USBLIBS = -L/usr/local/lib -lusb
и заменить на:
USBFLAGS = -I"c:/Program Files/LibUSB-Win32/include"
USBLIBS = -L"c:/Program Files/LibUSB-Win32/lib/gcc" -lusb
и обязательно проверить и убедиться в том что папки "include" и "gcc" располагаются по указанным путям если нет то их туда надо переместить перед этим найдя где они установлены или скачать и установить заново. Об этом написано на сайте: microsin.net. После внесения всех необходимых изменений Make файл надо сохранить и закрыть.
Далее открываем файл "set-led.c" и меняем исходный код (в первых пяти строках надо заменить #include" " на #include< >) на:


#include "windows.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "usb.h"        /* this is libusb */
#include "opendevice.h" /* common code moved to separate module */

#include "../firmware/requests.h"   /* custom request numbers */
#include "../firmware/usbconfig.h"  /* device's VID/PID and names */

#define USB_CFG_VENDOR_NAME     'e','l','e','c','t','e','.','b','l','o','g','s','p','o','t','.','c','o','m'
#define USB_CFG_VENDOR_NAME_LEN 19

#define USB_CFG_DEVICE_NAME     'm','y','u','s','b','d','e','v','i','c','e'
#define USB_CFG_DEVICE_NAME_LEN 11

const int BUTTON_ON_OFF=1000;

usb_dev_handle      *handle = NULL;
const unsigned char rawVid[2] = {USB_CFG_VENDOR_ID}, rawPid[2] = {USB_CFG_DEVICE_ID};
char                vendor[] = {USB_CFG_VENDOR_NAME, 0}, product[] = {USB_CFG_DEVICE_NAME, 0};
char                buffer[4];
int                  vid, pid;
unsigned short key_on_off=0;

/*  Declare Windows procedure  */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/*  Make the class name into a global variable  */
char szClassName[ ] = "WindowsApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nFunsterStil)

{
    HWND hwnd;               /* This is the handle for our window */
    MSG messages;            /* Here messages to the application are saved */
    WNDCLASSEX wincl;        /* Data structure for the windowclass */

    /* The Window structure */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default color as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Register the window class, and if it fails quit the program */
    if (!RegisterClassEx (&wincl))
        return 0;

    /* The class is registered, let's create the program*/
    hwnd = CreateWindowEx (
           0,                   /* Extended possibilites for variation */
           szClassName,         /* Classname */
           "Windows App",       /* Title Text */
           WS_OVERLAPPEDWINDOW, /* default window */
           CW_USEDEFAULT,       /* Windows decides the position */
           CW_USEDEFAULT,       /* where the window ends up on the screen */
           544,                 /* The programs width */
           375,                 /* and height in pixels */
           HWND_DESKTOP,        /* The window is a child-window to desktop */
           NULL,                /* No menu */
           hThisInstance,       /* Program Instance handler */
           NULL                 /* No Window Creation data */
           );

CreateWindow("button", "on/off", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,50, 50, 100,30, hwnd,(HMENU)BUTTON_ON_OFF,hThisInstance,NULL);

usb_init();

    vid = rawVid[1] * 256 + rawVid[0];
    pid = rawPid[1] * 256 + rawPid[0];


    if(usbOpenDevice(&handle, vid, vendor, pid, product, NULL, NULL, NULL) != 0){
MessageBox(hwnd, "Could not find USB device\n","error", 0);
        exit(1);
    }
else
{
MessageBox(hwnd, "Find USB device done!\n","Done!", 0);
}

    ShowWindow (hwnd, nFunsterStil);

    while (GetMessage (&messages, NULL, 0, 0))
    {
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
usb_close(handle);
    return messages.wParam;
}

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                
    {
        case WM_DESTROY:
            PostQuitMessage (0);    
        break;
case WM_COMMAND:
if(LOWORD(wParam)==BUTTON_ON_OFF)
            {
if(key_on_off==1)
{
usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_STATUS, 1, 0, buffer, 0, 5000);
key_on_off=0;
}
else
{
usb_control_msg(handle, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT, CUSTOM_RQ_SET_STATUS, 0, 0, buffer, 0, 5000);
key_on_off=1;
}
            }
break;
        default:                    
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
    return 0;
}



поля:
#define USB_CFG_VENDOR_NAME     'e','l','e','c','t','e','.','b','l','o','g','s','p','o','t','.','c','o','m'
#define USB_CFG_VENDOR_NAME_LEN 19

#define USB_CFG_DEVICE_NAME     'm','y','u','s','b','d','e','v','i','c','e'
#define USB_CFG_DEVICE_NAME_LEN 11
меняем на те что прописаны в файле "usbconfig.h"
Сохраняем и закрываем файл. Файлы "opendevice" (с расширением c и h) менять не надо. Файл "opendevice" с расширением c очень полезный в нём функция для более удобного "открытия" устройства. В папке где установлен libusb должна быть папка "include" в папке "include" должен быть файл "lusb0_usb.h" или что то в этом роде с расширением h этот файл надо скопировать в папку "include" где установлен MinGW и потом переименовать в "usb" расширение должно остаться h.
Открываем cmd (командную строку) и переходим в этой командной строке в папку "commandline"если папка v-usb находиться на диске d то сделать это можно 3мя командами:
cd c:\
d:
cd d:\vusb-20121206\examples\hid-custom-rq\commandline\
Далее для того чтобы откомпилировать пример вводится команда:
make
Если компиляция прошла успешно то в папке "commandline" должен появиться файл
"set-led.exe" -это и есть программа которая включает светодиод при нажатии кнопки.
Изменённый (немного криво но работающий) проект можно скачать с Яндекс диска.
Если всё сделано правильно то при запуске "set-led.exe" появится окно с кнопкой нажатие на которую приводит к включению светодиода, если устройство подключено к usb.
 Как видите реализация управления устройством через usb процесс довольно трудоёмкий и времязатратный но возможно результат всё таки стоит потраченного времени. 
КАРТА БЛОГА (содержание)

воскресенье, 7 сентября 2014 г.

Управление шаговым и коллекторными двигателями с компьютера.

В предыдущей статье рассматривался один из способов управления шаговым двигателем и приводилась схема. Шаговый двигатель управлялся через самодельный драйвер на транзисторах однако для маломощных двигателей всё же предпочтительнее использовать готовый драйвер например L239DD в smd корпусе (или L239D в корпусе DIP). Схема:
Рисунок 1 - ATtiny2313, LPT-порт и L239DD

Простой способ управления шаговым двигателем иллюстрируется на рисунке:

Рисунок 2 - Способ управления шаговым двигателем

Программу хранящую данную (см. рисунок 2) последовательность состояний и управляющую драйвером лучше хранить в микроконтроллере а на компьютере лучше хранить программу задающую направление и скорость вращения ротора двигателя, если на компьютере операционная система Windows. Это связано с тем что на компьютере труднее реализовать точные таймеры для управления двигателем. Немного переделанную программу (с исходниками), из предыдущей статьи, для управления двигателями можно скачать с Яндекс диска здесь (файл inpot32.dll по прежнему нужен для для работы программы и должен находится в той же папке что и эта программа). Программа для микроконтроллера не изменилась её можно скачать здесь.

КАРТА БЛОГА (содержание)