Одессит

Самодельный пульт управления для ПЧ серии Mitsubishi FR-E***

2 повідомлення у цій темі

Специально поднимаю свою тему с "того света". Ибо таки образовалось на нашей территории (в Украине) достаточное количество тех самых ПЧ (серия KN).
Интерес не сильно шкурный :)

Итак. ПЧ постоянно дешевеют. И я уже докатился до того, что сегодня прикрутил сей прибор для питания помпы СОЖ в ИЖ-е :)
А почему "нет"? Около 600 грн/помпа(маслонасос), и мы уже едем куда хотим. С любой скоростью (от одной фазы 220 и с ПЧ - 0,1кВт). Причём оба насоса ИЖ-а прекрасно всё качают на частоте 30 Гц, что приводит к снижению шума, потребления электроэнергии и снижению износа узлов насосов.
***
Как-то, в горячке закупок железок для ЧПУ-фрезера, недорого прикупил кучку частотных преобразователей Mitsubishi FR-E520-1.5 KN.
Всё бы хорошо. Но выяснилось, что эта серия заточена для работы исключительно из под шины управления CC-Link. Вот беда...
Т.е. управлять им по чипмейкерски (кнопки/крутилки) - никак!
Погоревал недельку да и купил “родной” пульт (подходит ко всем "мицикам") FR-PU04.
Данный пульт подключается к каналу RS-422 (Mitsubishi почему-то называет его 485-м. Но физически он таки 422-й, т.к. состоит из двух отдельных каналов приёма и передачи данных).
Работает. Не вопрос. НО!
1. Жаба (пульт обходится под 80 баксов).
2. Несколько жаб. Не покупать же пульт к каждому ПЧ!
3. Невозможность управления от внешнего терминала (кнопки и всё такое).

Да пёссым!
Прикрутил пульт к ПЧ. Промеж них прикрутил логический анализатор и стал выяснять что да как...
Выяснилось (попытки были и достаточно продолжительные), что управление с "компа" (согласно мануалу производителя) реализовать не получается (в данной серии функция наглухо обрезана).
Были "сняты" команды управления (и ответные посылки). Вычислен алгоритм их взаимодействия.
Применено квитирование. Команды похожи на описанные в мануале, но таки другие.
Под всё это дело написалась программка для AtMega-8 и создался внешний пультик управления предполагающий основные функции управления этим тарантасом.
Пультик укорочен до предела: вперёд-назад-стоп + три скорости. Устройство не предназначено для конфигурирования ПЧ! Зато будет работать практически с любым ПЧ от Mitsubishi.
Прилагаю схемку и программку. Предусмотрено два режима работы внешних «кнопок»: с фиксацией и без.
Принимайте КАК ЕСТЬ. В теле программы достаточно описаний для тех кто понимает. Для тех кто не понимает могу сказать, что есть ТРИ предустановленные скорости (50, 33 и 16 Герц). Комментариев там тоже достаточно. Разобраться не сложно.
На сегодня программа дописана до возможности регулирования скорости переменным резистором и отображения текущей частоты на LED-индикаторе (в данной версии отсутствует.)).

Схемка:
schem.jpg

 

Техзадание:

Скрытый текст

 

Управление частотным преобразователем Mitsubishi (имитация пульта PU4).

Используется Mega8/Mega8A * МГц в корпусе DIP-28. Используется внешний осциллятор на 7.3728 МГц.

Управление преобразователем производится по последовательной шине с использованием преобразователя RS232-RS485.

Параметры последовательного интерфейса – 7 бит, 1 стоп бит, без контроля четности. Скорость при установлении контакта – 4800, затем увеличивается до 19200 бит/с.

Органы управления – кнопка «Вперед», кнопка «Стоп», кнопка «Назад», трехпозиционный переключатель скорости.

Таблица 1. Назначение выводов mega8 (DIP-28)

PIN Имя In/Out Описание

23 PC0 (ADC0) —

24 PC1 (ADC1) In Задание скорости. 11 – большая скорость, 10 – средняя скорость, 01 – малая скорость, 00 – малая скорость

25 PC2 (ADC2) In

26 PC3 (ADC3) In Кнопка «Вперед», 0 – нажата

27 PC4 (ADC4) In Кнопка «Назад», 0 – нажата

28 PC5 (ADC5) In Кнопка «Стоп», 0 – нажата

 

14 PB0 (ICP) In Переключатель типа кнопок. 1 – с фиксацией, 0 – без фиксации

15 PB1 (OC1A) Out Индикатор аварии (красный), 0 – авария

16 PB2 (SS/OC1B) Out Индикатор движения назад (желтый), 0 – движение назад

17 PB3 (MOSI/OC2) Out Индикатор движения вперед (зеленый), 0 – движение вперед

18 PB4 (MISO) —

19 PB5 (SCK) —

 

2 PD0 (RXD) In Управление частотным преобразователем

3 PD1 (TXD) In

4 PD2 (INT0) —

5 PD3 (INT1) —

6 PD4 (T0) —

11 PD5 (T1) —

12 PD6 (AIN0) —

13 PD7 (AIN1) —

 

9 PB6 (XTAL1)

10 PB7 (XTAL2)

1 PC6 (RESET)

21 AREF

22 AGND

20 AVcc

8 GND

7 Vcc

Начинается с инициализации интерфейса на скорости 4800. Отправляется последовательность команд. Далее переводится скорость на 19200, выдается последовательность команд. Затем наступает вечный цикл посылки трех команд. Каждая из них имеет отклик. Две содержат состояние (вопрос как отличать). Третья – текущую частоту преобразователя.

Важно соблюдать интервалы между командами и проверять наличие и корректность отклика. Не забывать контролировать контрольную сумму и наличие кода 0x03.

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

Нажатие кнопок – фильтровать на интервале 50-100 мс. Скорость – усреднять на периоде 100 мс.

 

1. Инициализируем последовательный порт на работу 4800/7/1/«no parity».

2. Посылаем команду «0430».

3. Ждем ответ до 1 секунды. Нет ответа – переход на 2.

4. Если есть ответ «00001D4C4110» – переход на 5, иначе – переход на 2.

5. Посылаем команду «862563AD».

6. Ждем ответ до 1 секунды. Нет ответа – переход на 2.

7. Если есть ответ (0x06 0x46 0x46) – переход на 8, иначе – переход на 2.

8. Переводим последовательный порт на работу 19200/7/1/«no parity».

9. Посылаем команду «0431».

10. Ждем ответ до 100 мс.

11. Если есть ответ «00000000410» – переход на 12, иначе – переход на 1.

12. Посылаем команду «0500».

13. Ждем ответ до 100 мс.

14. Если есть ответ «BF009621» – переход на 15, иначе – переход на 1.

15. Посылаем команду «850034720720».

16. Ждем ответ до 100 мс.

17. Если есть ответ (0x06 0x46 0x46)– переход на 18, иначе – переход на 1.

18. Посылаем команду «0432».

19. Ждем ответ до 100 мс.

20. Если есть ответ «01F710001000» – переход на 21, иначе – переход на 1.

21. Посылаем команду «0510».

22. Ждем ответ до 100 мс.

23. Если есть ответ «1000» – переход на 24, иначе – переход на 1.

24. Посылаем команду «0660».

25. Ждем ответ до 100 мс.

26. Если есть ответ «01020300» – переход на 27, иначе – переход на 1.

27. Посылаем команду «03DF».

28. Ждем ответ до 200 мс.

29. Если есть ответ «013800003A00» – переход на 30, иначе – переход на 1.

30. Выполняется основной командный цикл.

Основной командный цикл.

1. Индекс равен 0.

2. Если есть команда оператора – переход на 3. Иначе – переход на 4.

3. Шлем команду оператора. Вперед – «85040002», Назад – «85040004», Стоп – «85040001». Переход на 5.

4. Шлем команду по индексу. Индекс 0 – «0510», индекс 1 – «0601», индекс 2 – «0627».

5. Ждем ответ до 100 мс.

6. Если была команда оператора, то сбрасываем команду оператора и переход на 9. Иначе – переход на 7.

7. Если индекс 0, то ответ должен быть «1X00», если индекс 1, то «SSSSSS41», если индекс 2, то «00001X00», где X – состояние преобразователя, а SSSSSS – частота вращения. Состояние преобразователя выводим на индикаторы. Скорость – игнорируем.

8. Увеличиваем индекс на 1. Если индекс больше 2, то индекс равен 0.

9. Переход на 2.

 

Состояние преобразователя (X) передается шестнадцатеричной цифрой (от 0 до F), где биты означают:

0 бит – если 1, то задано направление «вперед».

1 бит – если 1, то задано направление «назад».

2 бит – если 1, то выполняется движение «вперед».

3 бит – если 1, то выполняется движение «назад».

Примеры

0x35 – 5 (0101) задано направление «вперед» и движение идет «вперед».

0x31 – 1 (0001) задано направление «вперед», движения нет.

0x41 – A (1010) задано направление «назад» и движение идет «назад».

0x32 – 2 (0010) задано направление «вперед», движения нет.

Частота вращения (SSSSSS) в случае частоты в Гц выдается как шестнадцатеричное число из 6 цифр. После преобразования в десятичное число, частота получается делением на 100.

Например, получено число «000050». Ему соответствует десятичное число 80, что соответствует частоте 0.8 Гц. Второй пример – число «001388» соответствует десятичному числу 5000 или 50 Гц.

 

 

Собственно программа (пока без "потенциометра и показометра" (уже реализовано)).
 

Скрытый текст

 

Chip type : ATmega8

Program type : Application

AVR Core Clock frequency: 7.372800 MHz

Memory model : Small

External RAM size : 0

Data Stack size : 256

*****************************************************/

#include <mega8.h>

#include <delay.h>

#include <iobits.h>

#ifndef RXB8

#define RXB8 1

#endif

#ifndef TXB8

#define TXB8 0

#endif

#ifndef UPE

#define UPE 2

#endif

#ifndef DOR

#define DOR 3

#endif

#ifndef FE

#define FE 4

#endif

#ifndef UDRE

#define UDRE 5

#endif

#ifndef RXC

#define RXC 7

#endif

#define FRAMING_ERROR (1<<FE)

#define PARITY_ERROR (1<<UPE)

#define DATA_OVERRUN (1<<DOR)

#define DATA_REGISTER_EMPTY (1<<UDRE)

#define RX_COMPLETE (1<<RXC)

#define NUL 0x00

#define SOH 0x01

#define STX 0x02

#define ETX 0x03

#define EOT 0x04

#define ENQ 0x05

#define ACK 0x06

#define BEL 0x07

#define BS 0x08

#define HT 0x09

#define NL 0x0A

#define VT 0x0B

#define NP 0x0C

#define CR 0x0D

#define SO 0x0E

#define SI 0x0F

#define DLE 0x10

#define DC1 0x11

#define DC2 0x12

#define DC3 0x13

#define DC4 0x14

#define NAK 0x15

#define SYN 0x16

#define ETB 0x17

#define CAN 0x18

#define EM 0x19

#define SUB 0x1A

#define ESC 0x1B

#define FS 0x1C

#define GS 0x1D

#define RS 0x1E

#define US 0x1F

#define SP 0x20

// USART Receiver buffer

#define RX_BUFFER_SIZE 32

char rx_buffer[RX_BUFFER_SIZE]={0};

unsigned char rx_wr_index=0,rx_rd_index=0,rx_counter=0;

// This flag is set on USART Receiver buffer overflow

bit rx_buffer_overflow;

// USART Receiver interrupt service routine

interrupt [USART_RXC] void usart_rx_isr(void)

{

char status,data;

status=UCSRA;

data=UDR;

if ( (status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN)) == 0 )

{

rx_buffer[rx_wr_index++] = data;

if ( rx_wr_index == RX_BUFFER_SIZE )

{

rx_wr_index = 0;

}

if (++rx_counter == RX_BUFFER_SIZE)

{

rx_counter=0;

rx_buffer_overflow=1;

}

}

// Включаем таймер 0 для отслеживания завершения передачи (если в течение 5 мс не будет нового символа - конец передачи)

// Почему 5 мс - время передачи 2 символов на скорости 4800.

TCNT0=0x6F;

SETBIT(TIFR,0);

TIMSK=0x81;

}

#ifndef _DEBUG_TERMINAL_IO_

// Get a character from the USART Receiver buffer

#define _ALTERNATE_GETCHAR_

#pragma used+

char getchar(void)

{

char data = 0;

//while (rx_counter==0);

if ( rx_counter > 0 )

{

data = rx_buffer[rx_rd_index++];

if ( rx_rd_index == RX_BUFFER_SIZE ) rx_rd_index=0;

#asm("cli")

--rx_counter;

#asm("sei")

}

return data;

}

#pragma used-

#endif

// Write a character to the USART Transmitter

#ifndef _DEBUG_TERMINAL_IO_

#define _ALTERNATE_PUTCHAR_

#pragma used+

void putchar(char c)

{

while ((UCSRA & DATA_REGISTER_EMPTY) == 0);

UDR=c;

}

#pragma used-

#endif

#define MAX_REPLY_SIZE 32

char reply_cmd[MAX_REPLY_SIZE]={0};

bit bReply = 0;

// Timer 0 overflow interrupt service routine

// Срабатывает через 5 мс.

interrupt [TIM0_OVF] void timer0_ovf_isr(void)

{

char data, index;

// Отрубаем таймер

TIMSK=0x80;

// Копируем все, что накопилось из приемного буфера в буфер отклика

index = 0;

do

{

data = getchar();

reply_cmd[index] = data;

index++;

} while ( data );

bReply = 1;

PORTD.6 = !PORTD.6;

}

// Получить ответ на посланную команду

// 0 - нет ответа, 1 - ответ получен и помещено в pReply

char GetCmdReply(char* pReply)

{

char index = 0;

if ( bReply )

{

for ( ; index < MAX_REPLY_SIZE && reply_cmd[index] != 0; index++ )

{

PORTD.7 = !PORTD.7;

pReply[index] = reply_cmd[index];

reply_cmd[index] = 0;

}

pReply[index] = 0;

bReply = 0;

}

return (index == 0) ? 0 : 1;

}

// Standard Input/Output functions

#include <stdio.h>

#include <string.h>

char flash Station[] = "FF";

 

char flash Cmd_0430[] = "0430";

char flash Cmd_862563AD[] = "862563AD";

char flash Cmd_0431[] = "0431";

char flash Cmd_0500[] = "0500";

char flash Cmd_850034720720[] = "850034720720";

char flash Cmd_0432[] = "0432";

char flash Cmd_0660[] = "0660";

char flash Cmd_03DF[] = "03DF";

char flash Cmd_0510[] = "0510";

char flash Cmd_0601[] = "0601";

char flash Cmd_0627[] = "0627";

char flash CmdForward[] = "85040002";

char flash CmdRevers[] = "85040004";

char flash CmdStop[] = "85040001";

// Команды скорости в Гц.

//char flash CmdSpeedTemplate[] = "850200000000";

char CmdSpeedLarge[13] ="850200138800"; // 0x001388 = 5000 (50.00)

char CmdSpeedMedium[13]="8502000D0500"; // 0x000D05 = 3333 (33.33)

char CmdSpeedSmall[13] ="850200068300"; // 0x000683 = 1667 (16.67)

//char flash CmdSpeedTest[] = "85020003E800";

char flash ReplyNAK[] = {0x06, 0x46, 0x46, 0x00};

unsigned char CalcCheckSum(char* Str, unsigned char nLen)

{

unsigned char Sum = 0;

int i;

for ( i = 0; i < nLen; i++ )

{

if ( Str >= 0x20 )

Sum += Str;

}

return Sum;

}

void AddCheckSum(char* Cmd)

{

unsigned char CheckSum = CalcCheckSum(Cmd, strlen(Cmd));

int nLen = strlen(Cmd);

sprintf(Cmd+nLen, "%02X", CheckSum);

}

unsigned char TestCheckSum(char* Cmd, unsigned char* pLen, unsigned char WaitReply)

{

char sSum[3];

unsigned char CheckSum;

unsigned char bRet = 1;

unsigned char nLen = strlen(Cmd);

*pLen = nLen;

if ( nLen > 4 )

{

nLen -= 2;

CheckSum = CalcCheckSum(Cmd, nLen);

sprintf(sSum, "%02X", CheckSum);

if ( strcmp(sSum, Cmd + nLen) != 0 || strncmpf(Cmd+1, Station, 2) != 0 || Cmd[0] != WaitReply )

bRet = 0;

}

return bRet;

}

void MakeCommand(char* Cmd, char* CmdPart)

{

Cmd[0] = ENQ;

Cmd[1] = NUL;

strcatf(Cmd, Station);

strcat(Cmd, CmdPart);

AddCheckSum(Cmd);

}

enum SerialSpeed

{

S4800 = 0,

S19200= 1

};

void SetSerialSpeed(enum SerialSpeed NewSpeed)

{

switch (NewSpeed)

{

case S4800:

UBRRH=0x00;

UBRRL=0x5F;

break;

case S19200:

UBRRH=0x00;

UBRRL=0x17;

break;

}

}

void Indicate(unsigned char State)

{

if ( State >= 0x30 && State < 0x3A )

State -= 0x30;

else if ( State >= 0x41 && State < 0x47 )

State -= 0x37;

if ( State & 0x8 )

{

PORTB.2 = 0;

}

else

{

PORTB.2 = 1;

}

if ( State & 0x4 )

{

PORTB.3 = 0;

}

else

{

PORTB.3 = 1;

}

if ( (State & 0x2 && !(State & 0x8)) || (State & 0x1 && !(State & 0x4)) )

{

PORTB.1 = 0;

}

else

{

PORTB.1 = 1;

}

}

enum Phases

{

PhInit = 1,

PhWaitFirst = 2,

PhChangeSpeed = 3,

Ph_0431 = 4,

Ph_0500 = 5,

Ph_850034720720 = 6,

Ph_0432 = 7,

Ph_0510 = 8,

Ph_0660 = 9,

Ph_03DF = 10,

Ph_Cycle1 = 11,

Ph_Cycle2 = 12,

Ph_Cycle3 = 13,

Ph_UserCmd = 14

};

enum UserCommands

{

UCmdNone = 0,

UCmdStop = 1,

UCmdFwd = 2,

UCmdRvr = 3

};

enum Phases CurPhase = PhInit;

enum Phases StackPhase = PhInit; // Запомненное фаза работы - необходима для продолжения после команды пользователя

enum UserCommands UCmd = UCmdNone;

enum UserCommands UPrevCmd = UCmdNone;

// Типы обработок кнопок: с фиксацией и без

#define BUT_FIX 1

#define BUT_FREE 0

bit button_type = BUT_FREE;

// Маски обработок кнопок

#define BUT_MASK_FIX 0x18

#define BUT_MASK_FREE 0x38

// Коды кнопок

#define BUT_FIX_FWD 0x10

#define BUT_FIX_REV 0x08

#define BUT_FREE_FWD 0x30

#define BUT_FREE_REV 0x28

#define BUT_FREE_STOP 0x18

// Число раз считываний кнопок для подавления дребезга

#define MAX_BUT_COUNT 5

// Маска получения скорости

#define SPEED_MASK 0x06

// Скорости

enum Speeds

{

SpeedNone = 0x06,

SpeedSmall = 0x02,

SpeedMedium = 0x04,

SpeedLarge = 0x00

/* SpeedNone = 0x00,

SpeedSmall = 0x02,

SpeedMedium = 0x04,

SpeedLarge = 0x06 */

};

enum Speeds CmdSpeed = SpeedNone;

char flash* GetCmdStr(enum UserCommands FindCmd, unsigned char *TimeOut)

{

char flash* CmdPart = NULL;

switch ( FindCmd )

{

case UCmdStop:

CmdPart = CmdStop;

*TimeOut = 5;

break;

case UCmdFwd:

CmdPart = CmdForward;

*TimeOut = 5;

break;

case UCmdRvr:

CmdPart = CmdRevers;

*TimeOut = 5;

break;

}

return CmdPart;

}

char* GetSpeedStr(enum Speeds FindSpeed, unsigned char *TimeOut)

{

char* CmdPart = NULL;

switch ( FindSpeed )

{

case SpeedSmall:

CmdPart = CmdSpeedSmall;

break;

case SpeedMedium:

CmdPart = CmdSpeedMedium;

break;

case SpeedLarge:

CmdPart = CmdSpeedLarge;

break;

}

*TimeOut = 5;

return CmdPart;

}

char flash* GetCmdForPhase(enum Phases FindPhase, unsigned char *TimeOut)

{

char flash* CmdPart = NULL;

switch ( FindPhase )

{

case Ph_Cycle1:

CmdPart = Cmd_0510;

*TimeOut = 5;

break;

case Ph_Cycle2:

CmdPart = Cmd_0601;

*TimeOut = 8;

break;

case Ph_Cycle3:

CmdPart = Cmd_0627;

*TimeOut = 5;

break;

}

return CmdPart;

}

// Timer2 output compare interrupt service routine

// Срабатывает с периодом 10 мс.

interrupt [TIM2_COMP] void timer2_comp_isr(void)

{

static unsigned char ButtonCounter = 0;

static unsigned char PrevButtonState = 0;

static unsigned char TimeOut = 1;

static unsigned char BigTime = 0;

static unsigned char SpeedCounter = 0;

static enum Speeds PrevSpeed = SpeedNone;

static enum Speeds LastSendSpeed = SpeedNone;

static enum UserCommands TrrigeredCmd = UCmdNone;

enum Speeds CurSpeed;

enum UserCommands UCmdTemp = UCmdNone;

char Cmd[32];

char Reply[32];

unsigned char nLen;

unsigned char bFlag;

char CmdPartBuff[16];

char* CmdPart;

char flash* pFlashCmd;

unsigned char CurButtonState;

//long lSpeed;

//float fSpeed;

CmdPart = CmdPartBuff;

if ( button_type == BUT_FREE )

CurButtonState = PINC & BUT_MASK_FREE;

else

CurButtonState = PINC & BUT_MASK_FIX;

if ( CurButtonState == PrevButtonState )

{

ButtonCounter++;

if ( ButtonCounter >= MAX_BUT_COUNT )

{

// Устойчивое состояние!

if ( button_type == BUT_FREE )

{

if ( CurButtonState == BUT_FREE_STOP )

{

UCmdTemp = UCmdStop;

}

else if ( CurButtonState == BUT_FREE_FWD )

{

UCmdTemp = UCmdFwd;

}

else if ( CurButtonState == BUT_FREE_REV )

{

UCmdTemp = UCmdRvr;

}

}

else

{

if ( CurButtonState == BUT_FIX_FWD )

{

UCmdTemp = UCmdFwd;

TrrigeredCmd = UCmdTemp;

}

else if ( CurButtonState == BUT_FIX_REV )

{

UCmdTemp = UCmdRvr;

TrrigeredCmd = UCmdTemp;

}

else if ( TrrigeredCmd == UCmdFwd || TrrigeredCmd == UCmdRvr )

{

UCmdTemp = UCmdStop;

TrrigeredCmd = UCmdNone;

}

}

if ( UCmdTemp != UPrevCmd )

{

UCmd = UCmdTemp;

UPrevCmd = UCmd;

//TrrigeredCmd = UCmdTemp;

}

ButtonCounter = 0;

}

}

else

{

// Дребезг

PrevButtonState = CurButtonState;

ButtonCounter = 0;

}

CurSpeed = PINC & SPEED_MASK;

if ( CurSpeed == PrevSpeed )

{

SpeedCounter++;

if ( SpeedCounter >= MAX_BUT_COUNT )

{

// Устойчивое состояние и в CurSpeed новая скорость

if ( LastSendSpeed != CurSpeed )

{

// Если текущая скорость не такая как ранее - запоминаем скорость и посылаем ее

LastSendSpeed = CurSpeed;

}

else

{

// Иначе скорость посылать не надо

CurSpeed = SpeedNone;

}

CmdSpeed = CurSpeed;

SpeedCounter = 0;

}

else

{

CurSpeed = SpeedNone; // на этом цикле нет изменения скорости

}

}

else

{

// Дребезг

PrevSpeed = CurSpeed;

SpeedCounter = 0;

}

 

TimeOut--;

if ( TimeOut == 0 )

{

switch ( CurPhase )

{

case PhInit:

SetSerialSpeed(S4800);

CurPhase = PhWaitFirst;

strcpyf(CmdPart, Cmd_0430);

TimeOut = 8;

BigTime = 10;

break;

case PhWaitFirst:

if ( GetCmdReply(Reply) )

{

// Есть отклик - анализ

bFlag = 0;

if ( TestCheckSum(Reply, &nLen, STX) )

{

if ( strncmpf(Reply+3, "00001D4C4110", 12) == 0 )

{

// То что ждали

CurPhase = PhChangeSpeed;

strcpyf(CmdPart, Cmd_862563AD);

BigTime = 0;

TimeOut = 15;

bFlag = 1;

}

}

if ( !bFlag )

{

CurPhase = PhInit;

CmdPart = NULL;

TimeOut = 1;

}

}

else

{

// Нет отклика - ждем еще до истечения BigTime раз

CmdPart = NULL;

BigTime--;

if ( BigTime == 0 )

{

CurPhase = PhInit;

TimeOut = 1;

}

else

TimeOut = 12;

}

break;

case PhChangeSpeed:

if ( GetCmdReply(Reply) )

{

if ( strncmpf(Reply, ReplyNAK, 3) == 0 )

{

// То, что ждали

SetSerialSpeed(S19200); // Скорость делаем 19200

CurPhase = Ph_0431;

strcpyf(CmdPart, Cmd_0431);

BigTime = 0;

TimeOut = 4;

}

else

{

CurPhase = PhInit;

CmdPart = NULL;

TimeOut = 1;

}

}

else

{

// Нет отклика - ждем еще до истечения BigTime раз

CmdPart = NULL;

BigTime--;

if ( BigTime == 0 )

{

CurPhase = PhInit;

TimeOut = 1;

}

else

TimeOut = 5;

}

break;

case Ph_0431:

bFlag = 0;

if ( GetCmdReply(Reply) )

{

if ( TestCheckSum(Reply, &nLen, STX) )

{

if ( strncmpf(Reply+3, "000000004110", 12) == 0 )

{

// То что ждали

CurPhase = Ph_0500;

strcpyf(CmdPart, Cmd_0500);

TimeOut = 5;

bFlag = 1;

}

}

}

if ( !bFlag )

{

CurPhase = PhInit;

CmdPart = NULL;

TimeOut = 1;

}

break;

case Ph_0500:

bFlag = 0;

if ( GetCmdReply(Reply) )

{

if ( TestCheckSum(Reply, &nLen, STX) )

{

if ( strncmpf(Reply+3, "BF009621", 8) == 0 )

{

// То что ждали

CurPhase = Ph_850034720720;

strcpyf(CmdPart, Cmd_850034720720);

TimeOut = 5;

bFlag = 1;

}

}

}

if ( !bFlag )

{

CurPhase = PhInit;

CmdPart = NULL;

TimeOut = 1;

}

break;

case Ph_850034720720:

bFlag = 0;

if ( GetCmdReply(Reply) )

{

if ( strncmpf(Reply, ReplyNAK, 3) == 0 )

{

// То, что ждали

CurPhase = Ph_0432;

strcpyf(CmdPart, Cmd_0432);

TimeOut = 5;

bFlag = 1;

}

}

if ( !bFlag )

{

CurPhase = PhInit;

CmdPart = NULL;

TimeOut = 1;

}

break;

case Ph_0432:

bFlag = 0;

if ( GetCmdReply(Reply) )

{

if ( TestCheckSum(Reply, &nLen, STX) )

{

if ( strncmpf(Reply+3, "01F710001000", 12) == 0 )

{

// То что ждали

CurPhase = Ph_0510;

strcpyf(CmdPart, Cmd_0510);

TimeOut = 5;

bFlag = 1;

}

}

}

if ( !bFlag )

{

CurPhase = PhInit;

CmdPart = NULL;

TimeOut = 1;

}

break;

case Ph_0510:

bFlag = 0;

if ( GetCmdReply(Reply) )

{

if ( TestCheckSum(Reply, &nLen, STX) )

{

// То что ждали

CurPhase = Ph_0660;

strcpyf(CmdPart, Cmd_0660);

TimeOut = 5;

bFlag = 1;

}

}

if ( !bFlag )

{

CurPhase = PhInit;

CmdPart = NULL;

TimeOut = 1;

}

break;

case Ph_0660:

bFlag = 0;

if ( GetCmdReply(Reply) )

{

if ( TestCheckSum(Reply, &nLen, STX) )

{

if ( strncmpf(Reply+3, "01020300", 8) == 0 )

{

// То что ждали

CurPhase = Ph_03DF;

strcpyf(CmdPart, Cmd_03DF);

TimeOut = 15;

bFlag = 1;

}

}

}

if ( !bFlag )

{

CurPhase = PhInit;

CmdPart = NULL;

TimeOut = 1;

}

break;

case Ph_03DF:

bFlag = 0;

if ( GetCmdReply(Reply) )

{

if ( TestCheckSum(Reply, &nLen, STX) )

{

if ( strncmpf(Reply+3, "013800003A00", 12) == 0 )

{

// То что ждали

CurPhase = Ph_Cycle1;

strcpyf(CmdPart, Cmd_0510);

TimeOut = 5;

bFlag = 1;

}

}

}

if ( !bFlag )

{

CurPhase = PhInit;

CmdPart = NULL;

TimeOut = 1;

}

break;

case Ph_Cycle1:

if ( GetCmdReply(Reply) )

{

PORTD.7 = !PORTD.7;

if ( TestCheckSum(Reply, &nLen, STX) )

{

if ( nLen == 10 && Reply[3] == 0x31 && Reply[5] == 0x30 && Reply[6] == 0x30 )

{

Indicate(Reply[4]);

CurPhase = Ph_Cycle2;

// То что ждали - проверяем наличие команды. Если команда есть - выполняем ее.

if ( UCmd != UCmdNone )

{

// Есть команда пользователя

pFlashCmd = GetCmdStr(UCmd, &TimeOut);

if ( pFlashCmd ) strcpyf(CmdPart, pFlashCmd);

else CmdPart = NULL;

StackPhase = CurPhase;

CurPhase = Ph_UserCmd;

}

else if ( CmdSpeed != SpeedNone )

{

// Изменение скорости

CmdPart = GetSpeedStr(CmdSpeed, &TimeOut);

StackPhase = CurPhase;

CurPhase = Ph_UserCmd;

}

else

{

// Обычное поведение

pFlashCmd = GetCmdForPhase(CurPhase, &TimeOut);

if ( pFlashCmd ) strcpyf(CmdPart, pFlashCmd);

else CmdPart = NULL;

}

/*

if ( UCmd == UCmdNone )

{

CmdPart = GetCmdForPhase(CurPhase, &TimeOut);

//CmdPart = Cmd_0601;

//TimeOut = 8;

}

else

{

// Готовим посылку команды

CmdPart = GetCmdStr(UCmd, &TimeOut);

StackPhase = CurPhase;

CurPhase = Ph_UserCmd;

}

*/

}

}

}

break;

case Ph_Cycle2:

if ( GetCmdReply(Reply) )

{

if ( TestCheckSum(Reply, &nLen, STX) )

{

if ( nLen == 14 && Reply[9] == 0x34 && Reply[10] == 0x31 )

{

// То что ждали

// Выделяем скорость

//sscanf(Reply+3, "%6lx", &lSpeed);

//fSpeed = (float)lSpeed / 100.;

CurPhase = Ph_Cycle3;

// Проверяем наличие команды. Если команда есть - выполняем ее.

if ( UCmd != UCmdNone )

{

// Есть команда пользователя

pFlashCmd = GetCmdStr(UCmd, &TimeOut);

if ( pFlashCmd ) strcpyf(CmdPart, pFlashCmd);

else CmdPart = NULL;

StackPhase = CurPhase;

CurPhase = Ph_UserCmd;

}

else if ( CmdSpeed != SpeedNone )

{

// Изменение скорости

CmdPart = GetSpeedStr(CmdSpeed, &TimeOut);

StackPhase = CurPhase;

CurPhase = Ph_UserCmd;

}

else

{

// Обычное поведение

pFlashCmd = GetCmdForPhase(CurPhase, &TimeOut);

if ( pFlashCmd ) strcpyf(CmdPart, pFlashCmd);

else CmdPart = NULL;

}

/*

if ( UCmd == UCmdNone )

{

CmdPart = GetCmdForPhase(CurPhase, &TimeOut);

//CmdPart = Cmd_0627;

//TimeOut = 5;

}

else

{

// Готовим посылку команды

CmdPart = GetCmdStr(UCmd, &TimeOut);

StackPhase = CurPhase;

CurPhase = Ph_UserCmd;

}

*/

}

}

}

break;

case Ph_Cycle3:

if ( GetCmdReply(Reply) )

{

if ( TestCheckSum(Reply, &nLen, STX) )

{

if ( nLen == 14 && strncmpf(Reply+3, "00001", 5) == 0 && Reply[9] == 0x30 && Reply[10] == 0x30 )

{

// То что ждали

Indicate(Reply[8]);

CurPhase = Ph_Cycle1;

// Проверяем наличие команды. Если команда есть - выполняем ее.

if ( UCmd != UCmdNone )

{

// Есть команда пользователя

pFlashCmd = GetCmdStr(UCmd, &TimeOut);

if ( pFlashCmd ) strcpyf(CmdPart, pFlashCmd);

else CmdPart = NULL;

StackPhase = CurPhase;

CurPhase = Ph_UserCmd;

}

else if ( CmdSpeed != SpeedNone )

{

// Изменение скорости

CmdPart = GetSpeedStr(CmdSpeed, &TimeOut);

StackPhase = CurPhase;

CurPhase = Ph_UserCmd;

}

else

{

// Обычное поведение

pFlashCmd = GetCmdForPhase(CurPhase, &TimeOut);

if ( pFlashCmd ) strcpyf(CmdPart, pFlashCmd);

else CmdPart = NULL;

}

/*

if ( UCmd == UCmdNone )

{

CmdPart = GetCmdForPhase(CurPhase, &TimeOut);

//CmdPart = Cmd_0510;

//TimeOut = 5;

}

else

{

// Готовим посылку команды

CmdPart = GetCmdStr(UCmd, &TimeOut);

StackPhase = CurPhase;

CurPhase = Ph_UserCmd;

}

*/

}

}

}

break;

case Ph_UserCmd:

bFlag = 0;

if ( GetCmdReply(Reply) )

{

if ( strncmpf(Reply, ReplyNAK, 3) == 0 )

{

// То, что ждали

CurPhase = StackPhase;

pFlashCmd = GetCmdForPhase(CurPhase, &TimeOut);

if ( pFlashCmd ) strcpyf(CmdPart, pFlashCmd);

else CmdPart = NULL;

bFlag = 1;

}

}

if ( !bFlag )

{

CurPhase = PhInit;

CmdPart = NULL;

TimeOut = 1;

}

UCmd = UCmdNone;

break;

}

// Выводим команду.

if ( CmdPart )

{

MakeCommand(Cmd, CmdPart);

printf("%s", Cmd);

}

 

}

}

 

// Declare your global variables here

void main(void)

{

unsigned char i;

// Input/Output Ports initialization

// Port B initialization

// Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=Out Func1=Out Func0=In

// State7=T State6=T State5=T State4=T State3=1 State2=1 State1=1 State0=P

PORTB=0x0F;

DDRB=0x0E;

// Port C initialization

// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In

// State6=T State5=P State4=P State3=P State2=P State1=P State0=T

PORTC=0x3E;

DDRC=0x00;

// Port D initialization

// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In

// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T

PORTD=0x00;

DDRD=0xC0;

// Timer/Counter 0 initialization

// Clock source: System Clock

// Clock value: 28.800 kHz

TCCR0=0x04;

TCNT0=0x6F;

// Timer/Counter 0 initialization

// Clock source: System Clock

// Clock value: Timer 0 Stopped

//TCCR0=0x00;

//TCNT0=0x00;

// Timer/Counter 1 initialization

// Clock source: System Clock

// Clock value: Timer1 Stopped

// Mode: Normal top=0xFFFF

// OC1A output: Discon.

// OC1B output: Discon.

// Noise Canceler: Off

// Input Capture on Falling Edge

// Timer1 Overflow Interrupt: Off

// Input Capture Interrupt: Off

// Compare A Match Interrupt: Off

// Compare B Match Interrupt: Off

TCCR1A=0x00;

TCCR1B=0x00;

TCNT1H=0x00;

TCNT1L=0x00;

ICR1H=0x00;

ICR1L=0x00;

OCR1AH=0x00;

OCR1AL=0x00;

OCR1BH=0x00;

OCR1BL=0x00;

// Timer/Counter 2 initialization

// Clock source: System Clock

// Clock value: 7.200 kHz

// Mode: CTC top=OCR2

// OC2 output: Disconnected

ASSR=0x00;

TCCR2=0x0F;

TCNT2=0x00;

OCR2=0x47;

// External Interrupt(s) initialization

// INT0: Off

// INT1: Off

MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization

TIMSK=0x80;

//TIMSK=0x81;

// USART initialization

// Communication Parameters: 7 Data, 1 Stop, No Parity

// USART Receiver: On

// USART Transmitter: On

// USART Mode: Asynchronous

// USART Baud Rate: 4800

UCSRA=0x00;

UCSRB=0x98;

UCSRC=0x84; //0x8C

UBRRH=0x00;

UBRRL=0x5F;

// Analog Comparator initialization

// Analog Comparator: Off

// Analog Comparator Input Capture by Timer/Counter 1: Off

ACSR=0x80;

SFIOR=0x00;

// ADC initialization

// ADC disabled

ADCSRA=0x00;

// SPI initialization

// SPI disabled

SPCR=0x00;

// TWI initialization

// TWI disabled

TWCR=0x00;

 

// Добиваемся устойчивого сигнала о типе используемых кнопок

i = 0;

while( i < 10 )

{

i++;

if ( button_type != PINB.0 )

{

button_type = PINB.0;

i = 0;

}

}

// Инициализация значений скоростей

/*

char flash CmdSpeedTemplate[] = "850200000000";

char CmdSpeedLarge[13];

char CmdSpeedMedium[13];

char CmdSpeedSmall[13];

*/

 

// Global enable interrupts

#asm("sei")

while (1)

{

// Place your code here

//delay_ms(10);

}

}

 

 

 

 

 

7

Поділитися повідомленням


Посилання на повідомлення
Поділитися на інших сайтах

Не можу пройти не лайкнувши, хоч хтось реалізував, а тут ще й з сорцами.

0

Поділитися повідомленням


Посилання на повідомлення
Поділитися на інших сайтах

Створіть акаунт або увійдіть для коментування

Ви маєте бути користувачем, щоб залишити коментар

Створити акаунт

Зареєструйтеся для отримання акаунта. Це просто!


Зареєструвати акаунт

Увійти

Вже зареєстровані? Увійдіть тут.


Увійти зараз

  • Зараз на сторінці   0 користувачів

    Немає користувачів, які переглядають цю сторінку