Код рабочий MODBUS 100 опросов в секунду и больше позволяет на скорости порта 38400. Вроде таймауты корректные, чего не всегда встретишь, разделение времени. Измерение загрузки процессора осциллографом в цикле While (1) |outport; Все на прерываниях.
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
Тоже долго возился с протоколом ModBus, в итоге на avrfreaks попалась хорошая реализация , работает достаточно надежно.
.h Спойлер
Код:
#include "Macro.h" /* define baudrate of modbus */ #define MB_ADDR 0x0F #define BAUD 38400L #define UBRR ((F_CPU / 8 / BAUD ) -1) /* * Use 485 or 232, default: 485 * Use 232 for testing purposes or very simple applications that do not require RS485 and bus topology. */ #define PHYSICAL_TYPE 485 //possible values: 485, 232 /* * Definitions for transceiver enable pin. */ #define TRANSCEIVER_ENABLE_PORT PORTD #define TRANSCEIVER_ENABLE_PIN PD2 #define TRANSCEIVER_ENABLE_PORT_DDR DDRD /* * At the moment the user has to set the value for Baudrate and * speed mode manually. The values depend on the operating frequency * of your AVR and can be found in its datasheet. */ #define USART_TX USART_TX_vect #define USART_RX USART_RX_vect #define USART_UDRE USART_UDRE_vect #define UART_STATUS UCSR0A #define UART_CONTROL UCSR0B #define UART_DATA UDR0 #define UART_UDRIE UDRIE0 #define UCSRC UCSR0C #define RXCIE RXCIE0 #define TXCIE TXCIE0 #define RXEN RXEN0 #define TXEN TXEN0 #define UCSZ0 UCSZ00 #define U2X U2X0 #define UBRRH UBRR0H #define UBRRL UBRR0L /* * Available address modes. */ #define MULTIPLE_ADR 2 #define SINGLE_ADR 1 /* * Use SINGLE_ADR or MULTIPLE_ADR, default: SINGLE_ADR * This is useful for building gateways, routers or clients that for whatever reason need multiple addresses. */ #define ADDRESS_MODE SINGLE_ADR
/** * @brief Defines the maximum Modbus frame size accepted by the device. 255 is the default * and also the maximum value. However, it might be useful to set this to lower * values, with 8 being the lowest possible value, in order to save on ram space. */ #define MaxFrameIndex 255
/** * Modbus Function Codes * Refer to modbus.org for further information. * It's good practice to return exception code 01 in case you receive a function code * that you haven't implemented in your application. */ #define fcReadCoilStatus 1 //read single/multiple coils #define fcReadInputStatus 2 //read single/multiple inputs #define fcReadHoldingRegisters 3 //read analog output registers #define fcReadInputRegisters 4 //read analog input registers (2 Bytes per register) #define fcForceSingleCoil 5 //write single bit #define fcPresetSingleRegister 6 //write analog output register (2 Bytes) #define fcForceMultipleCoils 15 //write multiple bits #define fcPresetMultipleRegisters 16 //write multiple analog output registers (2 Bytes each) #define fcReportSlaveID 17 //read device description, run status and other device specific information
/* * Modbus Exception Codes * Refer to modbus.org for further information. * It's good practice to return exception code 01 in case you receive a function code * that you haven't implemented in your application. */ #define ecIllegalFunction 1 #define ecIllegalDataAddress 2 #define ecIllegalDataValue 3 #define ecSlaveDeviceFailure 4 #define ecAcknowledge 5 #define ecSlaveDeviceBusy 6 #define ecNegativeAcknowledge 7 #define ecMemoryParityError 8 /** * @brief Internal bit definitions */ #define BusTimedOut 0 #define Receiving 1 #define Transmitting 2 #define ReceiveCompleted 3 #define TransmitRequested 4 #define TimerActive 5 #define GapDetected 6 /** * @brief Configures the UART. Call this function only once. */ extern void modbusInit(void);
/** * @brief Current receive/transmit position */ extern volatile uint16_t DataPos;
/** * This only applies to single address mode. */ #if ADDRESS_MODE == SINGLE_ADR /** * @brief: Read the device address */ extern uint8_t modbusGetAddress(void);
/** * @brief: Set the device address * Arguments: - newadr: the new device address */ extern void modbusSetAddress(uint8_t newadr); #endif
/* @brief: Sends a response. * * Arguments: - packtop, index of the last byte in rxbuffer * that contains payload. Maximum value is * MaxFrameIndex-2. */ extern void modbusSendMessage(uint8_t packtop);
/* @brief: Discards the current transaction. For MULTIPLE_ADR-mode and general * testing purposes. Call this function if you don't want to reply at all. */ void modbusReset(void);
/** * @brief Call this function whenever possible and check if its return value has the ReceiveCompleted Bit set. * Preferably do this in the main while. I do not recommend calling this function within ISRs. * @example if (modbusGetBusState() & (1<<ReceiveCompleted)) { * modbusSendExcepton(ecIllegalFunction); * } */ extern uint8_t modbusGetBusState(void);
/** * @brief Call every 100us using a timer ISR. */ extern void modbusTickTimer(void); /** * @brief Returns amount of bits/registers requested. */ extern uint16_t modbusRequestedAmount(void);
/** * @brief Returns the address of the first requested bit/register. */ extern uint16_t modbusRequestedAddress(void);
/* A fairly simple and hopefully Modbus compliant 16 Bit CRC algorithm. * Returns 1 if the crc check is positive, returns 0 if it fails. * Appends two crc bytes to the array. */ extern uint8_t crc16(volatile uint8_t *ptrToArray,uint8_t inputSize); /* @brief: Handles single/multiple input/coil reading and single/multiple coil writing. * * Arguments: - ptrToInArray: pointer to the user's data array containing bits * - startAddress: address of the first bit in the supplied array * - size: input array size in the requested format (bits) * */ extern uint8_t modbusExchangeBits(volatile uint8_t *ptrToInArray, uint16_t startAddress, uint16_t size); /* @brief: Handles single/multiple register reading and single/multiple register writing. * * Arguments: - ptrToInArray: pointer to the user's data array containing registers * - startAddress: address of the first register in the supplied array * - size: input array size in the requested format (16bit-registers) * */ extern uint8_t modbusExchangeRegisters(volatile uint16_t *ptrToInArray, uint16_t startAddress, uint16_t size);
/* @brief: A fairly simple Modbus compliant 16 Bit CRC algorithm. * * Returns 1 if the crc check is positive, returns 0 and saves the calculated CRC bytes * at the end of the data array if it fails. * */ uint8_t crc16(volatile uint8_t *ptrToArray,uint8_t inputSize) //A standard CRC algorithm { uint16_t out=0xffff; uint16_t carry; uint8_t n; inputSize++; for (int l=0; l<inputSize; l++) { out ^= ptrToArray[l]; for (n = 0; n < 8; n++) { carry = out & 1; out >>= 1; if (carry) out ^= 0xA001; } } //out=0x1234; if ((ptrToArray[inputSize]==out%256) && (ptrToArray[inputSize+1]==out/256)) //check { return 1; } else { ptrToArray[inputSize]=out%256; //append Lo ptrToArray[inputSize+1]=out/256; //append Hi return 0; } }
/* @brief: copies a single or multiple words from one array of bytes to another array of bytes * amount must not be bigger than 255... * */ void listRegisterCopy(volatile uint8_t *source, volatile uint8_t *target, uint8_t amount) { for (uint8_t c=0; c<amount; c++) { *(target+c)=*(source+c); } }
/* @brief: copies a single bit from one char to another char (or arrays thereof) * * */ void listBitCopy(volatile uint8_t *source, uint16_t sourceNr,volatile uint8_t *target, uint16_t targetNr) { if(*(source+(sourceNr/8))&(1<<(sourceNr-((sourceNr/8)*8)))) { *(target+(targetNr/8))|=(1<<(targetNr-((targetNr/8)*8))); } else *(target+(targetNr/8))&=~(1<<(targetNr-((targetNr/8)*8))); }
/* @brief: Back to receiving state. * */ void modbusReset(void) { BusState=(1<<TimerActive); //stop receiving (error) modbusTimer=0; }
void modbusTickTimer(void) { if (BusState&(1<<TimerActive)) { modbusTimer++; if (BusState&(1<<Receiving)) //we are in receiving mode { if ((modbusTimer==modbusInterCharTimeout)) { BusState|=(1<<GapDetected); } else if ((modbusTimer==modbusInterFrameDelayReceiveEnd)) { //end of message BusState=(1<<ReceiveCompleted); #if ADDRESS_MODE == MULTIPLE_ADR if (crc16(rxbuffer,DataPos-3)) { //perform crc check only. This is for multiple/all address mode. } else modbusReset(); #endif #if ADDRESS_MODE == SINGLE_ADR if (rxbuffer[0]==Address && crc16(rxbuffer,DataPos-3)) { //is the message for us? => perform crc check } else modbusReset(); #endif } } else if (modbusTimer==modbusInterFrameDelayReceiveStart) BusState|=(1<<BusTimedOut); } }
void modbusInit(void) { UBRRH = (uint8_t)((UBRR) >> 8); UBRRL = (uint8_t) UBRR; UART_STATUS = (1<<U2X); //double speed mode. #ifdef URSEL // if UBRRH and UCSRC share the same I/O location , e.g. ATmega8 UCSRC = (1<<URSEL)|(3<<UCSZ0); //Frame Size #else UCSRC = (3<<UCSZ0); //Frame Size #endif UART_CONTROL = (1<<TXCIE)|(1<<RXCIE)|(1<<RXEN)|(1<<TXEN); // USART receiver and transmitter and receive complete interrupt #if PHYSICAL_TYPE == 485 TRANSCEIVER_ENABLE_PORT_DDR|=(1<<TRANSCEIVER_ENABLE_PIN); transceiver_rxen(); #endif BusState=(1<<TimerActive); }
/* @brief: Sends a response. * * Arguments: - packtop: Position of the last byte containing data. * modbusSendException is a good usage example. */ void modbusSendMessage(uint8_t packtop) { PacketTopIndex=packtop+2; crc16(rxbuffer,packtop); BusState|=(1<<TransmitRequested); DataPos=0; #if PHYSICAL_TYPE == 485 transceiver_txen(); #endif UART_CONTROL|=(1<<UART_UDRIE); BusState&=~(1<<ReceiveCompleted); }
/* @brief: Sends an exception response. * * Arguments: - exceptionCode * */ void modbusSendException(uint8_t exceptionCode) { rxbuffer[1]|=(1<<7); //setting MSB of the function code (the exception flag) rxbuffer[2]=exceptionCode; //Exceptioncode. Also the last byte containing data modbusSendMessage(2); }
/* @brief: Returns the amount of requested data objects (coils, discretes, registers) * */ uint16_t modbusRequestedAmount(void) { return (rxbuffer[5]|(rxbuffer[4]<<8)); }
/* @brief: Returns the address of the first requested data object (coils, discretes, registers) * */ uint16_t modbusRequestedAddress(void) { return (rxbuffer[3]|(rxbuffer[2]<<8)); }
/* @brief: copies a single or multiple bytes from one array of bytes to an array of 16-bit-words * */ void intToModbusRegister(volatile uint16_t *inreg, volatile uint8_t *outreg, uint8_t amount) { for (uint8_t c=0; c<amount; c++) { *(outreg+c*2) = (uint8_t)(*(inreg+c) >> 8); *(outreg+1+c*2) = (uint8_t)(*(inreg+c)); } }
/* @brief: copies a single or multiple 16-bit-words from one array of integers to an array of bytes * */ void modbusRegisterToInt(volatile uint8_t *inreg, volatile uint16_t *outreg, uint8_t amount) { for (uint8_t c=0; c<amount; c++) { *(outreg+c) = (*(inreg+c*2) << 8) + *(inreg+1+c*2); } }
/* @brief: Handles single/multiple register reading and single/multiple register writing. * * Arguments: - ptrToInArray: pointer to the user's data array containing registers * - startAddress: address of the first register in the supplied array * - size: input array size in the requested format (16bit-registers) * */ uint8_t modbusExchangeRegisters(volatile uint16_t *ptrToInArray, uint16_t startAddress, uint16_t size) { uint16_t requestedAmount = modbusRequestedAmount(); uint16_t requestedAdr = modbusRequestedAddress(); if (rxbuffer[1]==fcPresetSingleRegister) requestedAmount=1; if ((requestedAdr>=startAddress) && ((startAddress+size)>=(requestedAmount+requestedAdr))) {
if ((rxbuffer[1]==fcReadHoldingRegisters) || (rxbuffer[1]==fcReadInputRegisters) ) { if ((requestedAmount*2)<=(MaxFrameIndex-4)) //message buffer big enough? { rxbuffer[2]=(uint8_t)(requestedAmount*2); intToModbusRegister(ptrToInArray+(uint8_t)(requestedAdr-startAddress),rxbuffer+3,requestedAmount); modbusSendMessage(2+rxbuffer[2]); return 1; } else modbusSendException(ecIllegalDataValue); } else if (rxbuffer[1]==fcPresetMultipleRegisters) { if (((rxbuffer[6])>=requestedAmount*2) && ((DataPos-9)>=rxbuffer[6])) //enough data received? { modbusRegisterToInt(rxbuffer+7,ptrToInArray+(uint8_t)(requestedAdr-startAddress),(uint8_t)(requestedAmount)); modbusSendMessage(5); return 1; } else modbusSendException(ecIllegalDataValue);//too few data bytes received } else if (rxbuffer[1]==fcPresetSingleRegister) { modbusRegisterToInt(rxbuffer+4,ptrToInArray+(uint8_t)(requestedAdr-startAddress),1); modbusSendMessage(5); return 1; } //modbusSendException(ecSlaveDeviceFailure); //inapropriate call of modbusExchangeRegisters return 0; } else { modbusSendException(ecIllegalDataValue); return 0; } }
/* @brief: Handles single/multiple input/coil reading and single/multiple coil writing. * * Arguments: - ptrToInArray: pointer to the user's data array containing bits * - startAddress: address of the first bit in the supplied array * - size: input array size in the requested format (bits) * */ uint8_t modbusExchangeBits(volatile uint8_t *ptrToInArray, uint16_t startAddress, uint16_t size) { uint16_t requestedAmount = modbusRequestedAmount(); uint16_t requestedAdr = modbusRequestedAddress(); if (rxbuffer[1]==fcForceSingleCoil) requestedAmount=1; if ((requestedAdr>=startAddress) && ((startAddress+size)>=(requestedAmount+requestedAdr))) { if ((rxbuffer[1]==fcReadInputStatus) || (rxbuffer[1]==fcReadCoilStatus)) { if (requestedAmount<=((MaxFrameIndex-4)*8)) //message buffer big enough? { rxbuffer[2]=(requestedAmount/8); if (requestedAmount%8>0) { rxbuffer[(uint8_t)(requestedAmount/8)+3]=0x00; //fill last data byte with zeros rxbuffer[2]++; } for (uint16_t c = 0; c<requestedAmount; c++) { listBitCopy(ptrToInArray,requestedAdr-startAddress+c,rxbuffer+3,c); } modbusSendMessage(rxbuffer[2]+2); return 1; } else modbusSendException(ecIllegalDataValue); //too many bits requested within single request } else if (rxbuffer[1]==fcForceMultipleCoils) { if (((rxbuffer[6]*8)>=requestedAmount) && ((DataPos-9)>=rxbuffer[6])) //enough data received? { for (uint16_t c = 0; c<requestedAmount; c++) { listBitCopy(rxbuffer+7,c,ptrToInArray,requestedAdr-startAddress+c); } modbusSendMessage(5); return 1; } else modbusSendException(ecIllegalDataValue);//exception too few data bytes received } else if (rxbuffer[1]==fcForceSingleCoil) { listBitCopy(rxbuffer+4,0,ptrToInArray,requestedAdr-startAddress); modbusSendMessage(5); return 1; } //modbusSendException(ecSlaveDeviceFailure); //inanpropriate call of modbusExchangeBits return 0; } else { modbusSendException(ecIllegalDataValue); return 0; } }
Благодарю Вас, это один из немногих случаев, когда на радиокоте появляются исходники. Кстати, интересно, протестировать скорость и корректность таймаутов, так сказать конкурсные испытания провести. Есть между ними (кодами) коренное отличие, у меня, функция Main, в части цикла While, можно считать пустая и, посвящена исключительно подсчету так называемого Idle (простоя процессора смотрю осциллографом)
P.S. Ну и, конечно, все упрощено до предела реализации 3 и 6 функции с подсчетом CRC табличным методом для скорости, обратите внимание на аппаратную реализацию измерения таймаута...
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
astrahard, твоя программа при запуске требует кучу библиотек. В частности RTL60.BPL, vcl60.bpl, CPortLibCB5.bpl, возможно есть ещё, но третий файл я не нашёл для дальнейших попыток запуска программы. Вот статья где написано как отучить программу от bpl файлов: http://www.cyberforum.ru/cpp-builder/thread15180.html
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Спасибо, поленился исправлю попозже. Просто комп на котором все в гараже. Этот исходник помимо ModBus реализует цифровой ШИМ контроллер для компьютерного БП на замену TL494. Код мой. Если кому интересна тема полностью цифрового управления инвертором можно продолжить.
Добавлено after 22 minutes 18 seconds: Обратите внимание, что код выполнен полностью на прерываниях. В окончание функции Main() есть только маленький цикл реализующий Idle процесс, как во "Взрослых операционных системах" Осциллографом можно посмотреть насколько загружен процессор. Код выдает ШИМ сигнал для управления компьютерным БП заместо TL494, реализует ПИД регулятор и, параллельно может 100 опросов в секунду по протоколу ModBus на скорости 38400 и это не влияет на ШИМ и ПИД процессы, этот код также принимает уставки от хоста (ПК настольный) на изменение напряжения БП и снимает осциллограммы, и это все - этот маленький код. Кварц несколько нестандартный, но, я думаю, и на 16 МГц UART и ModBus будут работоспособны. На мой скромный взгляд этот код само совершенство....
Добавлено after 12 minutes 56 seconds: P.S. Если бы я писал операционную систему... Такой маленький код, выполняет столько функций в режиме реального времени... и ничто друг другу не мешается, а процессор загружен лишь на треть. А какое мастерское использование аппаратуры процессора, не, я положительно собой горжусь!
Добавлено after 29 minutes 30 seconds: Если кто захочет испытать на практике, то добавлю, что первый вход АЦП подключается к +5В каналу компьютерного БП (обратная связь) через резистивный делитель на 3 а конденсатор 10 нанофарад параллельно входу АЦП (антиалисинг фильтр).
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
astrahard, твоя программа при запуске требует кучу библиотек. В частности RTL60.BPL, vcl60.bpl, CPortLibCB5.bpl, возможно есть ещё, но третий файл я не нашёл для дальнейших попыток запуска программы. Вот статья где написано как отучить программу от bpl файлов: http://www.cyberforum.ru/cpp-builder/thread15180.html
Принес комп домой. Но Чего-то не срабатывает такой подход. - закладка linker: убрать галочку Use dinamyc RTL это я сделал и думал достаточно. А этот пункт - закладка packages: убрать галочку Build with runtimes packages вызывает ошибку компиляции. Дополнительный компонент СОМ порт говорит не найден, да и Build with runtimes packages вроде говорит о том чтобы включать packages. Чего-то здесь заморочено, я думал только линкеру надо указание дать.
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
Кроме своего приложения я управлял Мегой с помощью Модбас тестера функции 3 и 6. Тоже работает, правда он не позволяет опрашивать чаще 10-20 раз в секунду. У меня из своей программы получалось 100 опросов в сек.
Добавлено after 12 minutes 13 seconds: Получилось нашел я поиском "невидимые" файлы и, скопировал в папку с проектом. Можно было путь дополнительный прописать конечно.
Добавлено after 2 minutes 59 seconds: Только он залочен на СОМ3 всегда, недостаток, не позволяет выбрать порт. Еще недостаток ввод уставки происходит только когда кликнешь на другое поле ввода я нуб в программировании на ПК. Скорость 56000. Я разобрал устройство частично и не помню скорость. Кроме того у меня стояли инверторы на транзисторах перед подачей на контактные площадки выпаяной TL494. Не помню, исправил-ли в исходнике, вроде исправлял и, скорость порта изменил на 56000. Я пользовался Визардом CodeVision и, там менял полярность ШИМ сигнала.
P.S. И еще, нижняя строка там где копирайт нажимается и открываются дополнительные кнопки управления. Еще интересный факт, прошивал контроллер при подключенном в 220В БП и подключенном ШИМ заместо TL494 больше 100 раз и, ничего не сгорело!!!!
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
Вообще с портом можно работать и без компонента, как с текстовым файлом. Но если используешь компонент, то попробуй следующую конструкцию:
Код:
PortName := "COM1"; ComPort1->Port := PortName;
PortName - это переменная где хранится выбранный порт. Port - это название пункта у компонента куда вписываешь название использованного порта. Я не знаю как выглядит у тебя этот параметр, просто предположил. Ввод данных происходит потому что ты привязался к событию OnSelectили как-то так. Опять же я не вижу кода, а только предполагаю. Прятать дополнительные настройки, особенно кнопку закрытия порта, за не очевидную кнопку не лучшее решение. У тебя отсутствуют проверки ввода и выскакивают системные ошибки.
При подключенном к сети источнике лучше не прошивать потому что в этот момент могут вылететь ключи или напряжение на выходе выйти за пределы допустимые для нагрузки.
Спасибо большое за подсказки. А доп. настройки я спрятал в основном из-за пунктов включения и выключения ПИД регулятора. У меня еще осталась проблема, когда на большой нагрузке ПИД регулятор перестает справляться. На малых нагрузках все хорошо. И еще, я снял цифровым запоминающим осциллографом переходные процессы при включении, нагружении и разгрузке и, был приятно удивлен, что они лучше выглядят чем с родной TL494. Здорово и то, что на отключение конденсатора 10НФ в антиалисинг фильтре в делителе на 3 АЦП, который упомянут в исходнике, ПИД регулятор реагирует согласно теории, значит ПИД работает правильно. Планирую продолжить разработку на контроллерах dSPIC33EP64GS505-ISO и TMS320F28027 (TMS320F28016). Хочу доделать трехфазный ШИМ с осциллографированием на предмет сбоев в работе.
Добавлено after 1 hour 38 minutes 56 seconds: В связи с появлением очень дешевого контроллера stm8s003f3 у меня возникла идея переписать код под него. Можно получить полностью цифровой ШИМ контроллер для БП компьютеров и не только, с сервисом ввода уставок по напряжению, осциллографированием сбоев в работе ШИМ и сбоев сетевого питания и, диагностикой ухудшения характеристик деталей БП (конденсаторов сетевого фильтра, деградация силовых транзисторов и высыхание электролитов выпрямителя) с целью определения его остаточного ресурса. Это как Smart для жестких и твердотельных дисков. Кроме того здорово сократиться к-во деталей обвязки если учесть что stm8s003f3 не нуждается во внешнем кварце.
Добавлено after 6 minutes 18 seconds: И в самом деле, диагностика состояния батареи аккумуляторов есть, а диагностики состояния электролитов и силовых транзисторов в БП такого еще не было?
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
Хочешь мониторить помехи в питании? А контроллеру башню не снесёт при высыхании электролитов? И почему для управления выбран Modbus, а не свой протокол? Ведь он ориентирован для интеграции в разные SCADA системы.
Поэтому и выбран, что есть OPC сервер для ModBus и SCADA есть лайтовые удобные. Что касается не снесет-ли крышу контроллеру, у него-же есть собственный фильтр, да и потребляет он мало. кроме того я хочу развить проект на.
Выбор или двухядерный Microchip dsPIC33CH128MP508 или Texas Instruments TMS320F28027???? Это в плане ПО для управления трехфазным инвертором с ККМ чтобы было полностью цифровое управление (в том числе ККМ) с минимальной обвязкой деталями. Это я хочу сделать для мощных преобразователей электроэнергии (десятки киловатт, где вопрос цены не стоит так остро), как то 3Ф инвертор с ККМ, выпрямитель Виена с ККМ, векторное управление обобщенным электродвигателем с ККМ, MIG сварка на десятки киловатт без брызг с ККМ. Много лет назад уже начинал. Сейчас здорово продвинулся в понимании топологий и работы мощных инверторов и решил продолжить...
Добавлено after 3 minutes 6 seconds: P.S. Ну и, главное двинуть идею, чтобы было что реализовывать, вот например моя тема, которую лучше было-бы назвать "Датчик отказа датчика" http://forum.easyelectronics.ru/viewtop ... =9&t=39701
Добавлено after 5 hours 7 minutes 58 seconds: Просто мне показали однажды как работает OPC-ModBus сервер отдавая данные, например, напрямую в Excel и, мне понравилось. А какой еще путь для сверхбыстрой визуализации можно придумать?
Добавлено after 1 hour 57 minutes 43 seconds: Да, кстати. Визуализацию полученных от микроконтроллера данных очень удобно делать в Excel. Бесплатный modbus_opc_server_32tags можно найти и скачать, вариантов много, например https://insat.ru/products/?category=1666 как раз для отладки и некоммерческих проектов. Для радиолюбителя то что надо... Как известно, Excel позволяет написать в своей клеточки запрос к OPC серверу. А как это визуализировать поймет каждый пользователь электронной таблицы. Я не пойму, почему радиолюбители этим не пользуются?
Добавлено after 1 hour 52 seconds: Класс, мне удалось посрамить Немцев и фирму Ti, кажется, как авторов векторного управления обобщенным электродвигателем. Я упростил выражение для векторного регулирования и, упростил схему силовой части заодно, по моему, до сих пор, считалось, что упростить выражения векторного регулирования обобщенным электродвигателем невозможно. Вот не знаю что и думать, либо я раскрыл тайну Ti (их секретного наблюдателя InstaSPIN-FOC ), либо опередил их?
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
А ты не думал что сложность их схемы обусловлена не тупым управлением, а управлением с обратной связью, наличием защит и прочей ерундой? Ещё я обратил внимание что ты жёстко задаёшь адрес устройства в коде программы, это делает невозможным работу более одного устройства на шине. И ещё, использовать контроллер на 40 выводов, как замену микросхеме стоимостью в три раза дешевле не лучшая идея. Попробуй портировать код на ATtiny26L-8PU или STM8S003F3P6 например
Последний раз редактировалось radteh Пн ноя 25, 2019 15:26:44, всего редактировалось 1 раз.
Я не ту сложность имею ввиду, что вызвана "прочей ерундой" имеется ввиду выражения контура управления. Не я вполне серьезно. Вот рассуждения, которые привели меня к такому выводу. Это моя тема на сайте Электрик.орг http://www.electrik.org/forum/index.php?showtopic=71016 А также ШИМ в звене постоянного тока со своим ФНЧ может нести сразу две функции, генерацию 3-й гармоники для коммутатора и функцию ККМ "в одном флаконе".
P.S. Я как раз собираюсь портировать код на STM8S003F3P6. И исправить недочеты с "жесткой привязкой" это вызвано просто элементарной ленью и, легко уйдет в прошлое в очередном релизе.
Добавлено after 51 minute 35 seconds: Короче, для тех кто читает тему tp://www.electrik.org/forum/index.php?showtopic=71016 интересное замечание. ШИМ в звене постоянного тока, который питает, в свою очередь, 3-Ф 120 градусный коммутатор. Этот ШИМ может быть "Три в одном" тоесть нести три функции сразу 1. ККМ 2. Векторное регулирование 3. Фильтр ШИМ для того чтобы в двигатель не проникала высокая частота негативно сказывающаяся на изоляции обмоток. Для Этого ШИМ в звене постоянного тока должен выполнять нетривиальную, сложную модуляцию... В эту модуляцию войдет и закон управления, но все же, "уцелом" выражения закона управления и, "наблюдателя" упростятся, а вычисления станут более точными и быстрыми. Короче, вместо того чтобы ШИМить 3-Ф мостом, ну Вы поняли, а то я уже начинаю повторяться.
Добавлено after 1 minute 51 second: P.S. Приоритет на идею сохраняю за собой, буду делать реализацию и патентовать.
Добавлено after 37 minutes 41 second: И, в то-же время. Этот единый ШИМ и его закон, получаются очень простым, гораздо проще прежнего "фирменного". Ну я Голова, это-же надо такое придумать!!!!
_________________ "Every profession is a conspiracy against the uninitiated" (B. Shaw) "A textbook can be defined as a book unsuitable for reading" (B. Shaw) Tautology is humor in "this" place (Vigo Carpathian)
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 59
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения