วันพุธที่ 28 ธันวาคม พ.ศ. 2559

qt serial non-standard baudrate example, custom speed example ตัวอย่าง

เวลาที่เราต้องการใช้ serial port และ ใช้ baudrate ไม่มาตรฐาน ( custom baudrate, custom speed, non-standard baurate, non-standard speed ) ถ้าเป็นเครื่อง pc ทั่วไป ที่มี comport ติดมากับ mainboard ก็สามารถใช้ library ที่ Qt มีมาให้ได้ทันที แต่พอเป็น usb serial ต้องใช้วิธีเขียนอีกแบบนึง จึงจะสามารถใช้งาน custom speed ได้

กว่าจะหาวิธีที่ทำให้ rpi + qt + usb serial สามารถสื่อสารโดย custom speed  ได้ ค่อนข้างลำบาก (ข้อมูลค่อนข้างน้อย ใน google) ต้องรวบรวมข้อมูลจากหลายๆที่ แล้วมาทดลองทำดู ถึงจะได้ออกมา

ผู้เขียนเลือกใช้ usb serial ยี่ห้อ z-tek เวลาไปซื้อต้องบอกเจ้าของร้านว่าเอาของจริงเท่านั้น เพราะถ้าซื้อของปลอมมา จะใช้ไม่ได้ (ของปลอมทำเลียนแบบมีเยอะมาก และ ราคาก็ถูกกว่า) หรือถ้าใครมีความสามารถผลิต usb serial เองได้ โดยใช้ chipset ftdi ก็สามารถนำมาใช้ได้เหมือนกัน

มาดูตัวอย่าง code กันดีกว่า

#include <linux/serial.h>
#include <asm/termios.h>
#include <asm/ioctls.h>
#include <asm/termbits.h>
#include <stropts.h>
#include <QThread>

#include <fcntl.h>    /* For O_RDWR */
#include <unistd.h>   /* For open(), creat() */



main(){
int fd;
fd = open("/dev/ttyUSB0",O_RDWR|O_NOCTTY);


struct termios2 tio;
ioctl(fd, TCGETS2, &tio);
tio.c_cflag &= ~CBAUD;
tio.c_cflag |= BOTHER;
tio.c_ispeed = ความเร็วที่ต้องการ;
tio.c_ospeed = ความเร็วที่ต้องการ;
tio.c_cflag |= PARENB; // even parity
tio.c_cflag &= ~CSTOPB; // 1 stop bit
tio.c_cflag &= ~CSIZE;
tio.c_cflag |= CS8;

tio.c_cc[VTIME]=10; // wait 10 deciseconds

tio.c_cc[VMIN]=0;
ioctl(fd, TCGETS2, &tio);

========================================

พอมาทำกับ rpi4 แล้วใช้ไม่ได้ จึงเปลี่ยนเป็นแบบนี้

    struct termios2 tio;
    ioctl(fd, TCGETS2, &tio);
    tio.c_cflag &= ~CBAUD;
    tio.c_cflag |= BOTHER;
    tio.c_ispeed = 5760;
    tio.c_ospeed = 5760;
    tio.c_cflag |= PARENB; // even parity
    ioctl(fd, TCSETS2, &tio);
========================================
char ping_cmd[] = {2,1};
char ping_rec[7];
write(fd, &ping_cmd, sizeof(ping_cmd) );
QThread::msleep(1000);
read(fd, &ping_rec, sizeof(ping_rec));
write(fd, &ping_rec, sizeof(ping_rec) );
}

เมื่อ compile ผ่านแล้ว เราก็ต่อสายสัญญาณ USB232 จาก rpi เข้ากับ RS232 ของ notebook โดยไขว้ขา 2 กับ 3 สลับกันไว้
แล้วก็เปิดโปรแกรมอะไรก็ได้ที่สามารถสื่อสารผ่าน comport ได้
ในที่นี้ผู้เขียนได้ตั้งโปรแกรม comport ที่เครื่อง notebook ไว้ว่า ถ้ามี 0x01 ผ่านเข้ามา ให้ส่ง 0x61 ออกไป ก็จะได้ผลดังรูปด้านล่าง


จอบอ

ที่มา
http://stackoverflow.com/questions/12646324/how-to-set-a-custom-baud-rate-on-linux

https://blog.mbedded.ninja/programming/operating-systems/linux/linux-serial-ports-using-c-cpp/





วันพุธที่ 21 ธันวาคม พ.ศ. 2559

qt checkbox ตัวอย่าง

เริ่มจากการลาก GroupBox มาวางไว้ก่อน

แล้วลาก checkbox ลงมา สามารถลากลงมาได้หลายอัน ตามต้องการ โดยวางให้อยู่ใน GroupBox

เวลาเขียน code ก็พิมพ์ตามนี้

if(ui->radioButton->ischeck())
{
  QmessageBox::infomation(0,"message1","message2");
}

โดย message1 คือ title ที่อยู่ข้างบน bar
และ message2 คือ ข้อความที่ต้องการโชว์

ที่มา
https://www.youtube.com/watch?v=0XuxnBqGpWI

qt เปิด window ใหม่, เปิดหน้าต่างใหม่

ถ้าเราต้องการเปิดหน้าต่างใหม่ โดยใช้การกดปุ่ม ให้ทำดังนี้
1. คลิกขวาที่โปรเจค กด add new

ฝั่งซ้าย เลือก qt , ฝั่งขวาเลือก qt designer from class แล้วกด choose


แล้วตั้งชื่อหน้าต่างใหม่ตามต้องการ ในที่นี้ตั้งชื่อว่า SecDialog
จะมีหน้าต่างใหม่ขึ้นมา กด Diaglog without button กด next



2. ใน mainwindow.cpp ให้เพิ่ม #include "SecDialog.h"
3. ไปที่ mainwindow.h เพิ่ม #include "SecDialog.h"
4. mainwindow.h ตรง private: ให้เพิ่ม SecDialog *secdialog;
5. แล้วก็ไปที่ mianwindow.ui ให้คลิกขวาที่ปุ่มที่ต้องการให้เปิดหน้าต่างใหม่ เลือกไปที่ go to slot, click() แล้วพิมพ์ดังนี้
secdialog = new SecDialog(this);
secdialog-> show();

จบ
ที่มา https://www.youtube.com/watch?v=tP70B-pdTH0

qt วาดภาพ ตัวอย่าง

เนื่องจากใน qt ไม่ได้มีเครื่องมืออำนวยความสะดวกในการวาดภาพเหมือนโปรแกรม mspaint
เราจึงต้องเขียน code เพื่อวาดภาพเอง

ทำดังนี้

1. ใน main.h ให้เพิ่ม code เข้าไปใน class
protected:
  void paintEvent(QPaintEvent *e);


2. ใน mainwindow.cpp ให้เพิ่ม #include <QtGui>
และเพิ่มฟังก์ชัน
void mainwindow::paintEvent(QPaintEvent *e)
{
  QPainter p;
  p.begin(this);
  p.drawrect(0,0,50,50);
  หรืออยากวาดอะไรก็วาดไปได้เลย
}

ที่มา
https://www.youtube.com/watch?v=xXV3_mktCmY

วันอาทิตย์ที่ 18 ธันวาคม พ.ศ. 2559

qt sleep ตัวอย่าง

#include <QThread>

และตอนใช้ ก็ใช้แบบนี้

QThread::sleep(xx); โดย xx คือ ตัวเลข ในหน่วยวินาที

หรือ

QThread::msleep(xx); โดย xx คือ ตัวเลข ในหน่วยมิลลิวินาที 1,000 มิลลิวินาที = 1 วินาที

หรือ

QThread::usleep(xx); โดย xx คือ ตัวเลข ในหน่วยไมโครวินาที 1,000,000 มิลลิวินาที = 1 วินาที

วันพุธที่ 24 สิงหาคม พ.ศ. 2559

เปลี่ยน logo ตอน boot

ผมได้พยายามลองเปลี่ยนโลโก้ตอน boot ขึ้นมาใหม่ แต่ว่าทำได้แค่ใกล้เคียงที่อยากได้ มีขั้นตอนดังนี้
1. sudo apt-get install fbi
2. copy รูปภาพที่ต้องการให้โชว์ตอน boot ลงใน /etc แล้วตั้งชื่อว่า splash.png
3. สร้าง script ที่ /etc/init.d/asplashscreen ดังนี้

#! /bin/sh ### BEGIN INIT INFO # Provides: asplashscreen # Required-Start: # Required-Stop: # Should-Start: # Default-Start: S # Default-Stop: # Short-Description: Show custom splashscreen # Description: Show custom splashscreen ### END INIT INFO do_start () { /usr/bin/fbi -T 1 -noverbose -a /etc/splash.png exit 0 } case "$1" in start|"") do_start ;; restart|reload|force-reload) echo "Error: argument '$1' not supported" >&2 exit 3 ;; stop) # No-op ;; status) exit 0 ;; *) echo "Usage: asplashscreen [start|stop]" >&2 exit 3 ;; esac :

4. sudo chmod a+x /etc/init.d/asplashscreen (ทำให้ script สามารถใช้งานได้)
5. sudo insserv a+x /etc/init.d/asplashscreen
6. sudo nano /boot/cmdline.txt
6.1 เพิ่ม logo.nologo quiet เข้าไปข้างหลังสุด
7. sudo nano /etc/rc.local
7.1 เพิ่ม clear ก่อน exit 0
8. sudo reboot

ผลที่ได้คือ เราจะไม่เห็นลูก raspberry ตอนเริ่ม และจะเห็น logo ของเราในเวลาถัดมา
enjoy!!!

 

พฤ.18/02/2564

ผมได้มาทำใหม่ โดยทำตาม link ด้านล่างนี้ พบว่าได้ผลดี จึงนำมา share

https://www.thedigitalpictureframe.com/customize-your-raspberry-pi-splash-screen-raspbian-stretch-april-2019-version/ 

เริ่มต้นด้วยการ putty เข้าไป แล้วพิมพ์

fbset

จะได้หน้าตาคล้ายๆแบบนี้ออกมา

จะเห็นว่า ภาพที่เราจะใช้นั้น จะมีขนาด 480*800

จากนั้นเราก็ไปทำรูปของเราให้มีขนาดดังกล่าว ด้วยวิธีการอะไรก็แล้วแต่ ตามสบายเลย

แต่จะต้องตั้งชื่อรูปนั้นว่า splash.png

แล้วก็ remote รูป splash.png ที่เราสร้างมา ไปไว้ที่ /home/pi

แล้วก็ใช้คำสั่ง

sudo cp /home/pi/splash.png /usr/share/plymouth/themes/pix/splash.png

เพื่อนำรูปไปวางในตำแหน่งที่จะใช้เป็น logo ตอน boot

จากนั้น

sudo nano /boot/cmdline.txt

และเพิ่มนี่เข้าไปด้านท้าย

logo.nologo vt.global_cursor_default=0  

และเปลี่ยนจาก console=tty1 ให้เป็น tty3

ctrl+o, enter, ctrl+x

 

sudo nano /boot/config.txt 

เพิ่มนี่เข้าไปด้านล่างสุด

disable_splash=1

ctrl+o, enter, ctrl+x

 

sudo reboot

โชคดีครับ


วันจันทร์ที่ 11 กรกฎาคม พ.ศ. 2559

qt timer slot

ดูตามนี้เลยครับ ไม่มีเสียง ทำตามอย่างเดียวเลย
https://youtu.be/W1CTuOg2JLA

qt ตัวอย่างการส่ง serial port hex charactor, การรับค่า serial, การเปรียบเทียบ QByteArray กับ int

#include <QtSerialPort>
#include <QtSerialPort/QSerialPort>

void class::my_class()
{
    serial->setPortName("COM9");
    if (serial->isOpen()){
        serial->close();
        qDebug() << "serial close";
    }
    else{
        qDebug() << "serial already close.";
    }
    if (serial->open(QIODevice::ReadWrite)) {
        serial->setBaudRate(19200);
        serial->setDataBits(QSerialPort::Data8);
        serial->setParity(QSerialPort::EvenParity);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::NoFlowControl);          
    }
}

my_function()
{
    char buff[16];
    int hhh;
    for(hhh=0;hhh<=15;hhh++)
    {
        buff[0] = hhh;
        serial->write(buff,1);
    }
}


my_function2()
{
    QByteArray input;
    char buff[16];
    int hhh;
    for(hhh=0;hhh<=15;hhh++)
    {
        buff[0] = hhh;
        serial->write(buff,1);

        serial->waitForBytesWritten(100);
        serial->waitForReadyRead(100);
        input = serial->readAll();
        if (input == ""){
            qDebug() << "status" << hhh << " = Lost.";
        }else if( quint8(input[0]) == quint8(0x60+hhh)){
            qDebug() << "status" << hhh << " = Hot.";
        }
    }

    serial->flush();
}