自动喂鱼机

自动喂鱼机

自从上次成功驱动了报废光驱上拆下来的步进电机后,就一直想做一个能够自动定时喂鱼的装置,解决我周末或者长假回老家后鱼缸没人照料的窘境。一旦连续两天不喂食,那么必有最弱小的一条鱼会被啃得面目全非,所以我急需这样一个装置。
所有有志者事竟成,一切伟大的思想和行动都有一个微不足道的开始,最终还是让我把这样一个“产品”给做出来了,先不多说了,上一张图来看看。

下面详细讲解下实现的过程吧。

基础算法总结

基础算法总结

前段时间看了一部分《算法-第4版》,加深了我对排序、查找等基础算法的理解,在项目中更能够熟练的使用他们。所以这篇文章主要是按照我自己的理解对这些算法进行叙述,以方便日后浏览。文章可能有不严谨的地方,希望多多包涵。

排序

有很多操作都是基于有序序列的,所以排序算法可以说是基础中的基础,接下来就进行简单叙述。
排序算法的稳定性是值在有重复元素的排序操作后,等值有序元素的前后顺序不改变,否则即为不稳定。

冒泡排序

  • 中心思想: 对一个长度为N的无序数组进行N次冒泡,每次冒泡是将最大值冒泡到本次冒泡的末尾,每次从0开始到m结束(m=N-n,n表示第几次排序),依次两两比较。由于整个过程是从最大值到最小值依次冒泡到末尾,所以这个算法被形象地称为冒泡排序。
  • 时间复杂度: O(n^2)
  • 动图演示:

三星S8相机黑画面解决

三星S8相机黑画面解决

最近从媳妇儿那里入手了一个三星S8,所以就想着刷机,root试试。
但是手机刷机卸载系统软件后有遇到相机黑化面不能工作的情况,同时闪光灯也无法开启,人脸识别也无法使用。
具体情况如下图。

三星S8 刷机记录

三星Galaxy S8 刷机经验记录

这段时间用上了三星S8,由于原生系统太耗电,所以萌生了root的想法。写这篇博客记录下这段时间的各种尝试。

Root过程说明:

友情提示,道路千万条,安全第一条。开始捣鼓手机之前请一定准备好官方的救砖包。

  1. 解锁手机,我手上这台S8,时需要手机端先下载软件(crom1.0.8.apk)进行解锁;

  2. 刷入第三方recovery,我选择的TWRP,在TWRP官网上下载了针对我高通CPU版本的刷机包;

Socket编程基础

Socket编程之Socket基础

前言

Socket编程主要分为TCP/UDP/SCTP三种,每一种都有各自的优点,所以会根据实际情况决定选用何种Socket。
之后会抽取空余时间来开始深入学习Socket编程。

今天学习的是TCP编程。

基本流程:

TCP基本客户端与服务端的套接字函数:

  • Client:
    * socket
    * connect
    * write/read
    * close.
    

工作至今

2018年9月5日

距离毕业已经三年零两月。
三年的时间不算长,但是还是足够让我学到不少。直到昨天清除一个比较难解的bug之后,突然就想写点东西记录下三年走来的路。

2014年11月18日

记得那是个阴天,站在517的楼层,透过窗户看到的全是远处的雾。报到之后,被分配到了退改签组,从此开始了我的实习之旅。
当时主要是使用C#负责后端业务层,数据库操作,MVC框架什么的,当时还是比较熟的,但是当时完全只是为了使用而学习,并没有深层次的理解过,所以现在几乎忘完了:(。项目中使用的是敏捷开发,所以基本上每周都会迭代,记得应该是每周都会有3到5个需求需要完成。
我们旁边组就是前端组,他们人数不多,所以很多时候我们组有前端需求的时候,刚哥就会交给我,所以我在517的时候还学会了JS/Ajax/JQuery这些全端的知识。想想那个时候真的是白天黑夜,朝8晚9的。后来对于智能家居的向往,就离职了。开始朝着嵌入式的方向前进。那时候东哥给了我特别多的帮助,还有鲁班等等,不知道现在大家过得怎么样了。

巧用std::shared_ptr全局对象释放单例内存

单例内存释放

在程序中如果存在者单例,同时它们还需要执行delete等操作的话,我们通常在main的末尾去掉用单例的析构函数,或着利用编译器的属性,来设置main函数后执行的函数__attribute((destructor))
但是如果单例并不是在main函数所在的文件中定义的,那么就还需要想办法在main函数中访问它们,显得相对麻烦。

全局对象析构

在系统中全局对象都是由系统负责析构的,所以全局变量的析构函数,会在程序停止运行后,由系统调用执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>

class Test
{
public:
Test(int a)
{
std::cout << "Test Input: " << a << "." << std::endl;
}

~Test()
{
std::cout << "Test, destructor!" << std::endl;
}
};

Test test(88);

int main( void )
{
std::cout << "main...." << std::endl;
}

两相双极性步进电机驱动

前言

最近公司报废机器,所以我从要报废的机器中拆了不少零件,其中就在光驱中拆了迷你型步进电机(参见下图),在网上查阅资料了解到这个电机叫两相双极性步进电机

Hide Data into bitmap with ARGB8888 format

Hide Data into bitmap with ARGB8888 format

最近工作上接触Bitmap比较多,再加上之前就看到说如何利用图片的透明标志位来存放私密信息。
所以今天就动手写了这么个小工具,可以将一定长度的文本文件的内容隐藏到图片中保存起来,需要使用时再从图片中解码提取出来。

bitmap.h: 声明Bitmap的文件头结构,Bitmap类和数据隐藏类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#ifndef BMP_H
#define BMP_H

#include <fstream>
#include <string>
#include <iostream>

#define DEBUG 0

#define LOG std::cout
#define HEX std::hex
#define DEC std::dec

#define FLAG_0 (0xFF)
#define FLAG_1 (0xEE)
#define FLAG_2 (0xDD)
#define FLAG_3 (0xCC)

#define DATA_CODE (0xCC)

#define BYTE_PER_PIXEL (4)

#pragma pack(push, 1)
typedef struct
{
uint16_t bfType; // Type of bitmap, in windows, always 'BM'
uint32_t bfSize; // Size of the bitmap file
uint16_t bfReserved1; // reserved feild
uint16_t bfReserved2; // reserved feild
uint32_t bfOffBits; // the start address of the bitmap data
}BMP_FILE_HEADER;

typedef struct
{
uint32_t biSize; // size of this struct
uint32_t biWidth; // image width, unit is pixel
uint32_t biHeight; // image height, unit is pixel
uint16_t biPlanes; // alsways 1
uint16_t biBitCount; // color depth of the image, 1, 4, 8, 16, 24 and 32
uint32_t biCompression; // compression type, 0=no compress, 1=RLE8 compress
// 2=RLE4 compress, 3=pixel color mask
uint32_t biSizeImage; // pixel data size of the image
uint32_t biXPelsPerMeter; // H resolution, pixel per meter
uint32_t biYPelsPerMeter; // V resolution, pixel per meter
uint32_t biClrUsed; // color number that used, 0=all color
uint32_t biClrImportant; // important color amount, 0=all color important
}BMP_INFO_HEADER;
#pragma pacn(pop)

class Bitmap
{
private:
BMP_FILE_HEADER m_fileHeader;
BMP_INFO_HEADER m_infoHeader;

std::string m_bmpPath;
bool m_parseFlag;
public:
Bitmap(std::string path);
~Bitmap();
bool bmpParse();
uint32_t getBmpSize();
uint32_t getBmpDataAddr();
std::string getBmpPath();
uint32_t getBmpPixelNum();
};

class DataHider
{
private:
uint8_t m_flags[4];
uint8_t m_length[4];
Bitmap m_bitmapHeader;
std::string m_dataFilePath;

bool isAHider();
uint32_t getFileSize(std::ifstream &in);
bool readTransByte(std::fstream &file, uint8_t &val, int pos);
bool writeTransByte(std::fstream &file, uint8_t val, int pos);
void length2Byte(uint32_t length);
uint32_t byte2Length();
public:
DataHider(std::string dataPath, std::string bmpPath);
~DataHider();
bool doEncode();
bool doDecode();
};

#endif // BMP_H

binary and out mode to open a file

binary and out mode to open a file

When I use binary and out mode to open a exist file, and to modify the 4th and 8th byte data to 0x78, I found that the whole file will be rewrite, like below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <fstream>
#include <iostream>
using namespace std;

int main(int argc, char **argv)
{
fstream out;
out.open("./test.txt", ios_base::binary | ios_base::out);

uint8_t data = 0x78;

out.seekp(4, ios_base::beg);
out.write((char *)&data, 1);

out.seekp(8, ios_base::beg);
out.write((char *)&data, 1);

out.close();
return 0;
}