• Наслаждайтесь тем, что вы делаете, и вы никогда в своей жизни не будете работать.

Консоль на экране блока EV3

На экране блока EV3 мы имеем только прямой графический вывод, что не всегда удобно в случаях, когда нужно выводить текстовую информацию. Поэтому мы решили написать подпрограмму, обеспечивающую консольный вывод: с автоматическим сдвигом строк вниз, переносом строк, когда длина строки больше ширины экрана и т.п.

Для этого нужно было сначала определить, с чем мы будем работать: параметры экрана и возможные шрифты. Заглянув по этой ссылке на страницу, где описана работа с классом LCD (работа с ЖК экраном блока), узнаем, что:

  • ЖК экран блока EV3 — это черно-белый жидкокристаллический дисплей с размерами 44 × 29 мм и разрешением 178 × 128 точек.
  • Координаты точек отсчитываются от левого верхнего угла экрана, координаты левой верхней точки — (0; 0).
  • Текст на LCD экране блока Lego EV3 можно выводить только английскими буквами.
  • Шрифт текста может быть трех типов («размеров») «0», «1» или «2».
  • «0» — шрифт тонкий (толщина — 1 пиксель), имеет высоту 9 пикселей, ширину символа — 6 и вокруг — по 1 пробельному пикселю со всех сторон, кроме верха. Таким образом, одно знакоместо шрифта типа «0» составляет прямоугольник 10 × 8 пикселей. На экране можно уместить строку длиной 22 символа в ширину и 12 строк в высоту с учетом пробела в 1 пиксель между строками.
  • Шрифт типа «1» — жирный, его высота — 8 пикселей, ширина — 6 пикселей, и вокруг — по 1 пробельному пикселю со всех сторон, кроме верха. Таким образом, одно знакоместо шрифта типа «1» составляет прямоугольник 9 × 8 пикселей. На экране можно уместить строку длиной 22 символа в ширину и 14 строк в высоту с учетом пробела в 1 пиксель между строками.
  • Большой шрифт, тип «2» — жирный, имеет высоту 16 пикселей и ширину символа 14 пикселей, что с учетом пробельных пикселей дает знакоместо 17 х 16 пикселей. На экране можно уместить строку длиной 11 символов и количество таких строк с учетом пробела в 1 пиксель между строками — 7.
  • Если очередной символ в строке (справа) не помещается на экране целиком в ширину, то он не выводится, поэтому часть буквы у правого края экрана напечатана не будет, однако, это правило не работает по вертикали и поэтому внизу или сверху экрана можно напечатать неполную строку, используя, например, отрицательную координату Y. Также, это правило не работает для отрицательной координаты Х, что позволяет вывести слева неполный символ. Таким образом, например, возможно написание подпрограммы, осуществляющей плавный (попиксельный)  вертикальный скроллинг (прокрутку) текста.

Как и любая порядочная консоль наша консоль будет учитывать выбранный размер шрифта. Для того чтобы осуществлять последовательную прокрутку строк по вертикали мы должны создать буфер строк (массив), в котором будут храниться все выводимые на экран строки. При этом, как длина строк, так и их количество непосредственно зависят от выбранного типа шрифта.

Здесь мы реализовали два типа вывода текста:

  • стандартный (Scroll = 1): новая строка текста выводится в самой нижней строке экрана, весь остальной текст сдвигается снизу вверх — как в обычной консоли DOS/Win/Linux.
  • обратный (Scroll = -1): новая строка текста выводится в самой верхней строке экрана, весь остальной текст сдвигается сверху вниз.

Вероятно, для каких-то задач будет более предпочтителен второй (обратный вариант).

' В процессе работы программы эти переменные изменять нельзя: последствия  - непредсказуемы :)
FontType = 1 ' переменная, отвечающая за тип шрифта (0, 1 или 2)
Scroll = 1 ' прокрутка 1 - снизу вверх (как в обычной консоли DOS/Win/Linux), -1 - сверху вниз (для особых случаев)

' Консольный вывод на экран блока EV3 данных, находящихся в строке InString 
Sub EV3ConsoleWriteLine
    ' InString - строка для вывода в консоль
    ' StrN - номер экранной строки
    ' String[0] - массив экранных строк
    
    ' В соответствии с выбранным типом шрифта определяем необходимые константы консоли
    If FontType = 0 Then
        SimWidth = 8 ' ширина знакоместа
        SimHeight = 10 ' высота знакоместа
        ScrLength = 22 ' количество символов в строке
        ScrHeight = 12 ' количество строк на экране
    ElseIf FontType = 1 Then
        SimWidth = 8
        SimHeight = 9
        ScrLength = 22
        ScrHeight = 14
    ElseIf FontType = 2 Then
        SimWidth = 16
        SimHeight = 17
        ScrLength = 11
        ScrHeight = 7
    EndIf
    
    NStr = Math.Ceiling(Text.GetLength(InString) / ScrLength) ' считаем количество экранных строк массива для новой строки
    
    If Scroll = -1 Then ' Прокрутка сверху вниз (для особых случаев)
        ' Сдвигаем экранный массив на нужное количество строк вниз
        For StrN = (ScrHeight-1 - NStr) To 0 Step -1
            String[StrN + NStr] = String[StrN]
        EndFor
        ' Заполняем массив новой строкой, порезанной на куски нужной длины
        For StrN = 0 To NStr-1
            String[StrN] = Text.GetSubText(InString,ScrLength*StrN+1,ScrLength)
        EndFor
    ElseIf  Scroll = 1 Then ' Прокрутка снизу вверх (как в обычной консоли DOS/Win/Linux)
        ' Сдвигаем экранный массив на нужное количество строк вверх
        For StrN = 0 To (ScrHeight-1 - NStr)
            String[StrN] = String[StrN + NStr]
        EndFor
        ' Заполняем массив новой строкой, порезанной на куски нужной длины
        For StrN = ScrHeight - NStr To ScrHeight-1
            String[StrN] = Text.GetSubText(InString,ScrLength*(StrN-(ScrHeight-NStr))+1,ScrLength)
        EndFor
    EndIf
    
    ' Выводим массив на экран
    LCD.StopUpdate() ' блокируем непосредственный вывод на экран (будем выводить в буфер экрана)
    LCD.Clear() ' очищаем экран (и буфер)
    For StrN = 0 To ScrHeight-1 ' построчно выводим в буфер экрана массив строк
        Y = StrN * SimHeight
        LCD.Text(1,0,Y,FontType, String[StrN])
    EndFor
    LCD.Update() ' выводим все содержимое буфера
EndSub

' Ожидание нажатия любой кнопки блока c текстом
Sub EV3Wait
    InString = "Press any key..."
    EV3ConsoleWriteLine()
    Buttons.Flush()
    Buttons.Wait()
EndSub

' В качестве примера консольного вывода на экран блока воспользуемся алгоритмом нашей программы EV3 Test (https://smallbasic.rubasic.ru/test-bloka-ev3/)
InString = "EV3 name: " + EV3.BrickName ' записываем данные в строку вывода
EV3ConsoleWriteLine() ' вызов подпрограммы вывода строки InString в консоль
InString = "Bat. charge: " +  EV3.BatteryLevel + "%"
EV3ConsoleWriteLine()
InString = "Bat. voltage: " +  Text.GetSubText(EV3.BatteryVoltage,1,4) + " V"
EV3ConsoleWriteLine()
InString = "Bat. current: " +  Text.GetSubText(EV3.BatteryCurrent,1,4) + " A"
EV3ConsoleWriteLine()
InString = "Sensors:"
EV3ConsoleWriteLine()
InString = "Port Type Name Mode"
EV3ConsoleWriteLine()
For i = 1 To 4 ' последовательно проверяем все 4 порта датчиков
    InString = i + " " + Sensor.GetType(i) +  " " + Sensor.GetName(i) + " " + Sensor.GetMode(i)
    EV3ConsoleWriteLine()
EndFor

EV3Wait()

Вы можете скопировать этот код программы в IDE MS Small Basic, подключить блок EV3 и запустить.

Поделиться: