Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
products:laboratory_iot_c:exp55 [2024/12/15 17:45] – создано labuser30products:laboratory_iot_c:exp55 [2024/12/15 18:04] (текущий) – [Программный код эксперимента] labuser30
Строка 14: Строка 14:
 ==== Программный код эксперимента ==== ==== Программный код эксперимента ====
  
-<file python Exp55.py[enable_line_numbers="2", start_line_numbers_at="1"]> +<file arduino Exp55.ino[enable_line_numbers="2", start_line_numbers_at="1"]> 
-from machine import Pin, SPI +#include <SPI.h> 
-from tft import TFT_GREEN +#include <Adafruit_ST7735.h> 
-_init() +#include "LittleFS_ImageReader.h" 
-machine.freq(160000000)+
  
-dc  = Pin(4, Pin.OUT) +#define PIN_CS  2 
-cs  = Pin(2, Pin.OUT) +#define PIN_DC  4 
-rst = Pin(5, Pin.OUT) +#define PIN_RST 5
-spi = SPI(1, baudrate=40000000, polarity=0, phase=0)+
  
-tft = TFT_GREEN(128160spi, dc, cs, rst, rotate=0)+Adafruit_ST7735 tft = Adafruit_ST7735(PIN_CS PIN_DCPIN_RST)
 +LittleFS_ImageReader reader;
  
-Map [ +bool Map[10][8] = { 
-    [1,1,0,1,1,1,0,1]+  {1,1,0,1,1,1,0,1}
-    [0,1,1,1,1,1,1,0]+  {0,1,1,1,1,1,1,0}
-    [1,1,0,0,0,1,1,1]+  {1,1,0,0,0,1,1,1}
-    [0,1,0,1,0,1,0,1]+  {0,1,0,1,0,1,0,1}
-    [0,1,0,0,0,1,0,1]+  {0,1,0,0,0,1,0,1}
-    [1,1,1,1,0,0,0,1]+  {1,1,1,1,0,0,0,1}
-    [1,0,0,0,0,0,0,1]+  {1,0,0,0,0,0,0,1}
-    [1,0,0,0,1,0,0,1]+  {1,0,0,0,1,0,0,1}
-    [1,0,0,0,1,1,1,1]+  {1,0,0,0,1,1,1,1}
-    [1,1,1,1,1,0,0,0] +  {1,1,1,1,1,0,0,0} 
-]+};
  
-Gates [] +struct Pos { 
-Boxes []+  int x 0; 
 +  int y 0;
  
-class Box: +  bool operator == (const Pos &pos) const { 
-    def __init__(self, tft, x, y): +    return x == pos.x && y == pos.y; 
-        self.tft tft +  } 
-        self.x = x +};
-        self.y = +
-        self.picture 'box.bmp' +
-        self.picture_onGate = 'boxngate.bmp' +
-        self.onGate = False +
-        self.draw()+
  
-    def draw(self): +class Box { 
-        if (self.onGate)+  private
-            self.tft.draw_bmp(self.x 16,self.y 16,  self.picture_onGate) +    Adafruit_ST7735 *tft_ptr; 
-        else: +    LittleFS_ImageReader *reader_ptr; 
-            self.tft.draw_bmp(self.x * 16,self.y * 16, self.picture)+    Pos pos; 
 +    String picture = "/box.bmp"; 
 +    String picture_on_gate = "/boxngate.bmp"; 
 +    bool on_gate = false;
  
-    def setOnGate(self, state): +  public: 
-        self.onGate state+    Box(Adafruit_ST7735 *_tft_ptrLittleFS_ImageReader *_reader_ptr, int x, int y) { 
 +      tft_ptr = _tft_ptr; 
 +      reader_ptr = _reader_ptr; 
 +      pos.x = x; 
 +      pos.y = y; 
 +    }   
 +     
 +    void draw() { 
 +      if (on_gate) reader_ptr->drawBMP(picture_on_gate, *tft_ptr, pos.x * 16, pos.y * 16); 
 +      else reader_ptr->drawBMP(picture, *tft_ptr, pos.x * 16, pos.y * 16);  
 +    } 
 +  
 +    void setOnGate(bool state) 
 +      on_gate = state; 
 +    } 
 +         
 +    bool getOnGate() const { 
 +      return on_gate; 
 +    } 
 +  
 +    Pos getPos() const { 
 +      return pos; 
 +    } 
 +  
 +    void setPos(Pos _pos) {  
 +      pos._pos.x; 
 +      pos.y = _pos.y; 
 +      draw(); 
 +    } 
 +};        
  
-    def getOnGate(self)+class Gate { 
-        return self.onGate+  private
 +    Adafruit_ST7735 *tft_ptr; 
 +    LittleFS_ImageReader *reader_ptr; 
 +    Pos pos; 
 +    String picture  = "/gate.bmp";
  
-    def getPos(self)+  public
-        return (self.x, self.y)+    Gate(Adafruit_ST7735 *_tft_ptr, LittleFS_ImageReader *_reader_ptr, int x, int y) 
 +      tft_ptr = _tft_ptr; 
 +      reader_ptr = _reader_ptr; 
 +      pos.x = x; 
 +      pos.y = y; 
 +    } 
  
-    def setPos(selfxy): +    void draw() const { 
-        self.x = x +      reader_ptr->drawBMP(picture*tft_ptrpos.x * 16, pos.y * 16); 
-        self.y = y +    
-        self.draw()+
  
-class Gate: +    Pos getPos() const { 
-    def __init__(self, tft, x, y): +      return pos; 
-        self.tft = tft +    } 
-        self.x = x +};
-        self.y = y +
-        self.picture = 'gate.bmp' +
-        self.draw()+
  
-    def draw(self)+class Man { 
-        self.tft.draw_bmp(self.x 16,self.y 16, self.picture)+  private
 +    Adafruit_ST7735 *tft_ptr; 
 +    LittleFS_ImageReader *reader_ptr; 
 +    Pos pos; 
 +    String picture  = "/man.bmp";
  
-    def getPos(self): +  public: 
-        return (self.x, self.y)+    Man(Adafruit_ST7735 *_tft_ptr, LittleFS_ImageReader *_reader_ptr, int x, int y{ 
 +      Serial.println("Man constructor"); 
 +      tft_ptr = _tft_ptr; 
 +      reader_ptr = _reader_ptr; 
 +      pos.x = x; 
 +      pos.y = y; 
 +    } 
  
-class Man: +    void draw() const { 
-    def __init__(selftft, x, y): +      reader_ptr->drawBMP(picture*tft_ptrpos.* 16pos.* 16); 
-        self.tft = tft +    }
-        self.x = x +
-        self.y = y +
-        self.picture = 'man.bmp' +
-        self.draw()+
  
-    def draw(self): +    Pos getPos() const { 
-        self.tft.draw_bmp(self.x * 16,self.y * 16, self.picture)+      return pos; 
 +    }
  
-    def getPos(self): +    void setPos(Pos _pos 
-        return (self.x, self.y)+      tft_ptr->fillRect(pos.x * 16pos.y * 16, 16, 16, ST77XX_BLACK)
 +      pos.x = _pos.x; 
 +      pos.y = _pos.y; 
 +      draw(); 
 +    } 
 +};
  
-    def setPos(self, xy): +class Button { 
-        self.tft.rect(self.x * 16, self.y * 16, 16, 16, tft.COLOR_BLACK+  private: 
-        self.x x +    int pin; 
-        self.y y +    bool pressState; 
-        self.draw()+    bool oldState; 
 +  
 +  public:  
 +    Button(int _pinbool _pressState{ 
 +      pin = _pin; 
 +      setPinMode(); 
 +      pressState _pressState; 
 +      oldState = not _pressState; 
 +    } 
 +  
 +    bool onPress() { 
 +      bool state = digitalRead(pin); 
 +      if (state != oldState){ 
 +        oldState state; 
 +        if (state == pressStatereturn true; 
 +      } 
 +      return false; 
 +    }
  
-class Button: +    void setPinMode() const { 
-    def __init__(self, p, pressSate): +      pinMode(pin, INPUT); 
-        self.pin = Pin(pPin.IN) +    } 
-        self.pressSate = pressSate +}; 
-        self.oldState = 0 +
-     +
-    def onPress(self): +
-        state = self.pin.value() +
-        if state != self.oldState: +
-            self.oldState = state +
-            if state == self.pressSate: +
-                return True +
-        return False+
  
-tft.initr(tft.BGR) # tft.initr(tft.RGB) #Если вместо синего цвета отображается красныйа вместо красного синий +const int boxes_number = 3; 
-tft.clear(tft.COLOR_BLACK)+Box boxes[boxes_number] = { 
 +  {&tft, &reader, 3, 4}, 
 +  {&tft, &reader, 4, 6}, 
 +  {&tft, &reader, 2, 7},   
 +};
  
-0 +const int gates_number 3; 
-0+Gate gates[gates_number] 
 +  {&tft, &reader, 6, 3}, 
 +  {&tft, &reader, 6, 4}, 
 +  {&tft, &reader, 6, 5},   
 +};
  
-for row in Map: +Man man(&tft, &reader56);
-    for col in row: +
-        if col: +
-            tft.draw_bmp(x * 16y * 16,'brick.bmp') +
-        x+=1 +
-    x=0 +
-    y+=1+
  
-Boxes.append(Box(tft3,4)+Button btn_up(16, HIGH); 
-Boxes.append(Box(tft4,6)+Button btn_down(15HIGH); 
-Boxes.append(Box(tft2,7))+Button btn_left(12HIGH); 
 +Button btn_right(0LOW);
  
-Gates.append(Gate(tft, 6,3)) +bool canMove(Pos pos) { 
-Gates.append(Gate(tft, 6,4)) +  if (Map[pos.y][pos.x]return false; 
-Gates.append(Gate(tft, 6,5))+  else return true; 
 +
 +  
 +int feelBox(Pos pos{ 
 +  for (int i = 0; i < boxes_number; i++) { 
 +    if (boxes[i].getPos() == pos) return i; 
 +  } 
 +  return -1; 
 +
 +  
 +bool boxOnGate(Pos pos
 +  for (int i = 0; i < gates_number; i++{ 
 +    if (gates[i].getPos() == posreturn true; 
 +  } 
 +  return false; 
 +}
  
-man = Man(tft, 5, 6)+void setup() { 
 +  Serial.begin(9600); 
 +  Serial.println(); 
 +  Serial.println("Setup"); 
 +  LittleFS.begin(); 
 +  tft.initR(INITR_BLACKTAB); 
 +  tft.setRotation(2); 
 +  tft.fillScreen(ST77XX_BLACK)
  
-btnUp Button(16, 1+  for (int y 0; y < 10; y++{ 
-btnDown Button(15, 1+    for (int x 0; x < 10; x++{ 
-btnLeft = Button(12, 1) +      if (Map[y][x]reader.drawBMP("/brick.bmp"tft, x * 16, y * 16)
-btnRight = Button(00)+    } 
 +  } 
  
-def canMove(x,y): +  for (int i = 0; i < boxes_number; i++{ 
-    if (Map[y][x])+    boxes[i].draw(); 
-        return False +  }
-    else: +
-        return True+
  
-def feelBox(x,y): +  for (int i = 0; i < gates_number; i++{ 
-    for B in Boxes: +    gates[i].draw()
-        if B.getPos() == (x,y)+  } 
-            return B +   
-    return False+  man.draw();
  
-def boxFeelGate(x,y): +  btn_left.setPinMode(); 
-    for G in Gates: +}
-        if G.getPos() == (x,y): +
-            return True +
-    return False+
  
-while True: +void loop() { 
-    mPos = man.getPos() +  Pos man_pos = man.getPos(); 
-    newPos (-1,-1)+  Pos new_pos {-1, -1}; 
 +  Pos new_pos_next = {-1, -1};
  
-    if btnUp.onPress(): +  if (btn_up.onPress()) { 
-        newPos (mPos[0]mPos[1]-1) +    new_pos {man_pos.xman_pos.y - 1}; 
-        newPosNext (mPos[0]mPos[1]-2)+    new_pos_next {man_pos.xman_pos.y - 2}; 
 +  }
  
-    if btnDown.onPress(): +  if (btn_down.onPress()) { 
-        newPos (mPos[0]mPos[1]+1) +    new_pos {man_pos.xman_pos.y + 1}; 
-        newPosNext (mPos[0]mPos[1]+2)+    new_pos_next {man_pos.xman_pos.y + 2}; 
 +  }
  
-    if btnLeft.onPress(): +  if (btn_left.onPress()) { 
-        newPos (mPos[0]-1, mPos[1]) +    new_pos {man_pos.x - 1, man_pos.y}; 
-        newPosNext (mPos[0]-2, mPos[1])+    new_pos_next {man_pos.x - 2, man_pos.y}; 
 +  }
  
-    if btnRight.onPress(): +  if (btn_right.onPress()) { 
-        newPos (mPos[0]+1, mPos[1]) +    new_pos {man_pos.x + 1, man_pos.y}; 
-        newPosNext (mPos[0]+2, mPos[1])+    new_pos_next {man_pos.x + 2, man_pos.y}; 
 +  }
  
-    if newPos !(-1,-1): +  Pos not_pos {-1, -1};
-        B = feelBox(newPos[0], newPos[1]) +
-        if B and canMove(newPosNext[0], newPosNext[1]): +
-            if boxFeelGate(newPosNext[0], newPosNext[1]): +
-                B.setOnGate(True) +
-            else: +
-                B.setOnGate(False) +
-            B.setPos(newPosNext[0], newPosNext[1]) +
-            man.setPos(newPos[0], newPos[1]) +
-        if not B and canMove(newPos[0], newPos[1]): +
-            man.setPos(newPos[0], newPos[1])+
  
-        for G in Gates: +  if (!(new_pos == not_pos)) { 
-            gPos G.getPos() +    int box feelBox(new_pos); 
-            if not (feelBox(gPos[0], gPos[1])) and gPos != man.getPos(): +    if (box >= && canMove(new_pos_next)) 
-                G.draw()+      if (boxOnGate(new_pos_next)) boxes[box].setOnGate(true); 
 +      else boxes[box].setOnGate(false)
  
-        win = 1 +      boxes[box].setPos(new_pos_next); 
-        for B in Boxes: +      man.setPos(new_pos); 
-            if (not B.getOnGate()): +    } 
-                win = 0 + 
-                break +    if (box == -&& canMove(new_pos)) man.setPos(new_pos); 
-         + 
-        if (win)+    for (int i = 0; i < gates_number; i++) { 
-            tft.draw_bmp(0, 16,  'win.bmp'+      if (feelBox(gates[i].getPos()) == -1 and !(man.getPos() == gates[i].getPos())) { 
-            raise SystemExit+        gates[i].draw(); 
 +      } 
 +    } 
 + 
 +  } 
 + 
 +  bool win = true; 
 + 
 +  for (int i = 0; i < boxes_number; i++) 
 +  { 
 +    if (!boxes[i].getOnGate()){ 
 +      win = false; 
 +      break; 
 +    } 
 +  } 
 + 
 +  if (win) reader.drawBMP("/win.bmp", tft, 0, 0) 
 +}
 </file> </file>
  
Строка 220: Строка 306:
 ''canMove(x, y)'' — проверяет возможность перемещения кладовщика или ящика в заданную координату. Эта функция просто проверяет наличие стены в данном месте. Если ее там нет — значит переместиться в эту координату можно. Если стена есть, то нельзя. ''canMove(x, y)'' — проверяет возможность перемещения кладовщика или ящика в заданную координату. Эта функция просто проверяет наличие стены в данном месте. Если ее там нет — значит переместиться в эту координату можно. Если стена есть, то нельзя.
  
-<code python[enable_line_numbers="2", start_line_numbers_at="136"]> +<code arduino[enable_line_numbers="2", start_line_numbers_at="180"]> 
-def canMove(x,y): +bool canMove(Pos pos{ 
-    if (Map[y][x])+  if (Map[pos.y][pos.x]) return false; 
-        return False +  else return true; 
-    else+}
-        return True+
 </code> </code>
  
-Функция ''feelBox(x, y)'' — проверяет наличие ящика в заданной координате. Эта проверка происходит при движении кладовщика. Если перед ним находится ящик, то он должен сдвинуться. Функция перебирает все объекты ящиков и сравнивает их координаты с заданной. Если на пути есть ящик, то возвращается ссылка на объект этого ящика, иначе возвращается False+Функция ''feelBox(x, y)'' — проверяет наличие ящика в заданной координате. Эта проверка происходит при движении кладовщика. Если перед ним находится ящик, то он должен сдвинуться. Функция перебирает все объекты ящиков и сравнивает их координаты с заданной. Если на пути есть ящик, то возвращается индекс объекта этого ящика в массиве, иначе возвращается -1. 
-<code python[enable_line_numbers="2", start_line_numbers_at="142"]> + 
-def feelBox(x,y): +<code arduino[enable_line_numbers="2", start_line_numbers_at="185"]> 
-    for B in Boxes: +int feelBox(Pos pos{ 
-        if B.getPos() == (x,y): +  for (int i = 0; i < boxes_number; i++) { 
-            return B +    if (boxes[i].getPos() == posreturn i; 
-    return False+  } 
 +  return -1; 
 +}
 </code> </code>
  
-Функция ''boxFeelGate(x,y)'' — проверяет находится ли ящик на цели. В качестве параметров функция принимает координату ящика и проверяет наличие цели с такой же координатой. +Функция ''boxOnGate()'' — проверяет находится ли ящик на цели. В качестве параметров функция принимает координату ящика и проверяет наличие цели с такой же координатой. 
-<code python[enable_line_numbers="2", start_line_numbers_at="148"]> + 
-def boxFeelGate(x,y): +<code arduino[enable_line_numbers="2", start_line_numbers_at="192"]> 
-    for G in Gates: +bool boxOnGate(Pos pos{ 
-        if G.getPos() == (x,y)+  for (int i = 0; i < gates_number; i++) { 
-            return True +    if (gates[i].getPos() == pos) return true; 
-    return False+  } 
 +  return false; 
 +}
 </code> </code>
  
Строка 249: Строка 338:
  
 Если нажатие было и новая координата определена, то происходит проверка новой координаты. Сначала мы проверяем есть ли на пути кладовщика ящик: Если нажатие было и новая координата определена, то происходит проверка новой координаты. Сначала мы проверяем есть ли на пути кладовщика ящик:
-<code python[enable_line_numbers="2", start_line_numbers_at="175"]> +<code arduino[enable_line_numbers="2", start_line_numbers_at="255"]> 
-        = feelBox(newPos[0], newPos[1])+        int box = feelBox(new_pos);
 </code> </code>
  
-Если ящик есть, значит мы должны двигаться вместе с ящиком. Но для этого нужно проверить может ли передвинуться ящик (нет ли стены перед ящиком). +Если ящик есть (индекс больше или равен 0), значит мы должны двигаться вместе с ящиком. Но для этого нужно проверить может ли передвинуться ящик (нет ли стены перед ящиком). 
-<code python[enable_line_numbers="2", start_line_numbers_at="176"]> +<code python[enable_line_numbers="2", start_line_numbers_at="256"]> 
-        if B and canMove(newPosNext[0], newPosNext[1]):+    if (box >= 0 && canMove(new_pos_next){
 </code> </code>
  
-Если все в порядке и ящик может передвинуться, то проверяем еще одно условие — находится ли ящик на цели. Если да, то B.setOnGate(True), если нет, то B.setOnGate(False).+Если все в порядке и ящик может передвинуться, то проверяем еще одно условие — находится ли ящик на цели. Если да, то boxes[box].setOnGate(True), если нет, то boxes[box].setOnGate(False).
  
 После чего передвигаем ящик и кладовщика в новую координату. После чего передвигаем ящик и кладовщика в новую координату.
Строка 265: Строка 354:
  
 Далее идет вспомогательная логика. В частности мы перерисовываем цели, если на них нет ящика или кладовщика. Это нужно, чтобы после прохождения ящика или кладовщика по цели они прорисовывались заново, но не прорисовывались поверх ящика или кладовщика: Далее идет вспомогательная логика. В частности мы перерисовываем цели, если на них нет ящика или кладовщика. Это нужно, чтобы после прохождения ящика или кладовщика по цели они прорисовывались заново, но не прорисовывались поверх ящика или кладовщика:
-<code python[enable_line_numbers="2", start_line_numbers_at="186"]> +<code arduino[enable_line_numbers="2", start_line_numbers_at="266"]> 
-        for G in Gates: +    for (int i = 0; i < gates_number; i++{ 
-            gPos = G.getPos() +      if (feelBox(gates[i].getPos()) == -1 and !(man.getPos() == gates[i].getPos())) { 
-            if not (feelBox(gPos[0], gPos[1])) and gPos !man.getPos(): +        gates[i].draw()
-                G.draw()+      } 
 +    }
 </code> </code>
  
-Далее идет проверка условия выигрыша. Игра считается выигранной когда все ящики установлены на свои цели. Для этого мы проверяем условие нахождения ящика на цели для каждого ящика. Если у всех ящиков соблюдается данное условие, то игра выиграна. А когда она выиграна на дисплее отображается победная картинка осуществляется выход из программы: +Далее идет проверка условия выигрыша. Игра считается выигранной когда все ящики установлены на свои цели. Для этого мы проверяем условие нахождения ящика на цели для каждого ящика. Если у всех ящиков соблюдается данное условие, то игра выиграна. А когда она выиграна на дисплее отображается победная картинка. 
-<code python[enable_line_numbers="2", start_line_numbers_at="191"]> +<code arduino[enable_line_numbers="2", start_line_numbers_at="274"]> 
-        win = 1 +  bool win = true; 
-        for B in Boxes: + 
-            if (not B.getOnGate()): +  for (int i = 0; i < boxes_number; i++) 
-                win = 0 +  { 
-                break +    if (!boxes[i].getOnGate()){ 
-         +      win = false; 
-        if (win)+      break; 
-            tft.draw_bmp(0, 16,  'win.bmp') +    } 
-            raise SystemExit+  } 
 + 
 +  if (win) reader.drawBMP("/win.bmp", tft, 0, 0)
 </code> </code>