You guessed it -)) is a geothermal heat pump controller. The first version supports the start-stop compressor, now I run the second version with frequency control of the BLDC compressor.
The frequency converter is used, Omron MX2, link on modbus.
Regarding the operating system for the free rtos.
Any operating system solves three main tasks:
- The division of “computer time” between tasks
- Memory allocation between tasks
- Division of hardware between tasks.
Free rtos first two problems and provides tools for solving the third task (mutexes and semaphores)
How to solve the problem of “dividing” spi between two devices (wiznet and SD card) is an example in the code below:
Two switching functions are implemented
// SPI switching functions between two devices
inline void SPI_switchW5200 ()
{
DigitalWriteDirect (4, HIGH);
DigitalWriteDirect (10, LOW);
}
inline void SPI_switchSD ()
{
DigitalWriteDirect (10, HIGH);
DigitalWriteDirect (4, LOW);
}
Example of file transfer over the network:
// Чтение с карты файлов
SPI_switchSD();
if (!card.exists(filename)) // проверка на сущестование файла
{
SPI_switchW5200();
sendConstRTOS(thread,HEADER_FILE_NOT_FOUND);
journal.jprintf((char*)"$WARNING - Can't find %s file!\n",filename);
return;
} // файл не найден
for(i=0;i<SD_REPEAT;i++) // Делаем SD_REPEAT попыток открытия файла
{
if (!webFile.open(filename, O_READ)) // Карта не читатаеся
{
if (i>=SD_REPEAT-1) // Исчерпано число попыток
{
SPI_switchW5200();
sendConstRTOS(thread,HEADER_FILE_NOT_FOUND);
journal.jprintf("$ERROR - opening %s for read failed!\n",filename);
HP.message.setMessage(pMESSAGE_SD,(char*)"Ошибка открытия файла с SD карты",0); // сформировать уведомление об ошибке чтения
HP.set_fSD(false); // Отказ карты, работаем без нее
return;
}//if
}
else break; // Прочиталось
vTaskDelay(50/portTICK_PERIOD_MS);
journal.jprintf("Error opening file %s repeat open . . .\n",filename);
} // for
SPI_switchW5200(); // переключение на сеть
// Файл открыт читаем данные и кидаем в сеть
#ifdef LOG
journal.jprintf("$Thread: %d socket: %d read file: %s\n",thread,Socket[thread].sock,filename);
#endif
sendConstRTOS(thread,HEADER_FILE_WEB);
SPI_switchSD();
while ((n=webFile.read(Socket[thread].outBuf,sizeof(Socket[thread].outBuf))) > 0)
{
SPI_switchW5200();
if (sendBufferRTOS(thread,(byte*)(Socket[thread].outBuf),n)==0) break;
SPI_switchSD();
} // while
SPI_switchSD();
webFile.close();
SPI_switchW5200();
From the code it is clear how the SPI is switched
But this does not solve the problem completely!
We do not forget that we have a multitasking web server, and two tasks (a web server stream) can access the SPI simultaneously.
There is still a transmission level using binary semaphores:
Example code below:
uint16_t sendPacketRTOS(uint8_t thread, const uint8_t * buf, uint16_t len,uint16_t pause)
{
uint8_t status=0;
uint16_t ret=0;
uint16_t freesize=0;
uint8_t s=Socket[thread].sock;
SPI_switchW5200();
if (len > W5100.SSIZE) ret = W5100.SSIZE; else ret = len;
if (pause==0) // Честно ждем ack
{
do // Ожидание освобождения буфера
{
xSemaphoreGive(HP.xThreadSemaphore); // Мютекс потока отдать
taskYIELD();
if (xSemaphoreTake(HP.xThreadSemaphore,(W5200_TIME_WAIT/portTICK_PERIOD_MS))==pdFALSE) {journal.jprintf("Socket: %d mutex is buzy\n",s); return 0;} // Захват мютекса потока или ОЖИДАНИНЕ W5200_TIME_WAIT
taskENTER_CRITICAL();
freesize = W5100.getTXFreeSize(s);
if (freesize>=ret) {taskEXIT_CRITICAL(); break;}
status = W5100.readSnSR(s);
taskEXIT_CRITICAL();
if ((status != SnSR::ESTABLISHED) && (status != SnSR::CLOSE_WAIT)) { ret = 0; break; }
}
while (freesize < ret);
}
else // Не ждем ACK а просто делаем задержку
{
xSemaphoreGive(HP.xThreadSemaphore); // Мютекс потока отдать
vTaskDelay(pause/portTICK_PERIOD_MS); // Ждем pause мсек
if (xSemaphoreTake(HP.xThreadSemaphore,(W5200_TIME_WAIT/portTICK_PERIOD_MS))==pdFALSE) {journal.jprintf("Socket: %d mutex is buzy\n",s); return 0;} // Захват мютекса потока или ОЖИДАНИНЕ W5200_TIME_WAIT
}
if(GETBIT(Socket[thread].flags,fABORT_SOCK)) {SETBIT0(Socket[thread].flags,fABORT_SOCK);return 0;} // Произошел сброс прерываем передачу
// послать данные
taskENTER_CRITICAL();
W5100.send_data_processing_offset(s, 0, (uint8_t *)buf,ret);
W5100.execCmdSn(s,Sock_SEND);
taskEXIT_CRITICAL();
// +2008.01 bj : reduce code
while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
{
if ( W5100.readSnSR(s) == SnSR::CLOSED )
{
close(s);
return 0;
}
}
W5100.writeSnIR(s, SnIR::SEND_OK);
return ret;
}
A very important point these three lines
xSemaphoreGive(HP.xThreadSemaphore); // Мютекс потока отдать
taskYIELD();
if (xSemaphoreTake(HP.xThreadSemaphore,(W5200_TIME_WAIT/portTICK_PERIOD_MS))==pdFALSE) {journal.jprintf("Socket: %d mutex is buzy\n",s); return 0;} // Захват мютекса потока или ОЖИДАНИНЕ W5200_TIME_WAIT
About the use of one web page.
Heat pumps are installed in the countryside. Internet only through the cellular network (2G 3G 4G). Speed of 1-8 megabits per second, so to accelerate the loading it is interesting to “split” the files into small pieces.
Also I want to note that wiznet chips do not have a pipeline. Sending the packet the chip expects to receive an ACK before sending the next packet, and the transmission speed is highly dependent on the ping network.
In the cellular network (ping 40-50 msec) my server’s transmission rate drops to 30-40 kbps. To speed up, I entered a special mode without waiting for the ACK, running on delays. The speed in this mode reaches 300 kbps. What is an acceptable result.
I did some work and put the server on a “bad” network stably.
Additional options can be found at http://77.50.254.24:25401/lan.html
Libraries and free RTOS.
Here it is necessary to look that for libraries and where are used.
Library problems when using free RTOS
- Monopoly capture of the entire processor time. (Using delay). You need to adjust the code. But for example OneWire is friendly with free RTOS
- “hardware” divisions - semaphores to help you
- We always remember that another task can change the variable.
I have consistently worked 14 tasks with 5 priorities.
My record is uptime more than 23 days, then I updated the software -)