sudo pacman -S texlive-most texlive-langchinese
manjaro软件仓库里的 texlive 比较精简,没有附带宏包手册所以 texdoc 不能用, latex 初学者还是建议去CTAN下载完整镜像手动安装。我是为了编译之前写好的文件所以没有手册影响不大。(原本写作环境Deepin挂掉了)
sudo pacman -S texlive-most texlive-langchinese
manjaro软件仓库里的 texlive 比较精简,没有附带宏包手册所以 texdoc 不能用, latex 初学者还是建议去CTAN下载完整镜像手动安装。我是为了编译之前写好的文件所以没有手册影响不大。(原本写作环境Deepin挂掉了)
单位 G3930 电脑的windows 10系统最近更新几次失败后就频繁死机,被迫重装,于是grub就无了。为啥要重装windows,而不是Linux only呢,因为我搞不定Linux下的打印机 Orz Windows 10的打印机其实也有bug,最著名的便是 KB5006670 导致远程smb打印机连接失败,一顿折腾后参考真解决Win10最新补丁导致共享打印问题 通过替换 win32spl 文件解决了。
微软官网直接提供了ISO下载地址,不需要安装工具: https://www.microsoft.com/en-us/software-download/windows10ISO
sudo pacman -Syu woeusb
sudo woeusb --device /home/manjaro/迅雷下载/Win10_21H2_Chinese_x64.iso /dev/sdb
windows下我习惯用rufus制作各类安装U盘,Linux下 woeusb 是个不错的命令行工具,用法和 dd 类似,更多用法可以通过 man 查询。注意提供的文件名不要太复杂,比如
sudo woeusb --device /home/manjaro/迅雷下载/Win10_21H2_Chinese(Simplified)_x64.iso /dev/sdb
就会执行失败,推测原因是圆括号不能正常识别。
傻瓜操作
以下步骤在 Manjaro live usb 中进行,或者其他自己惯用的Linux发行版,制作好安装U盘后启动即可。
su
mount /dev/sda8 /mnt
mount mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
chroot /mount
grub-install --target i386-pc /dev/sda
update-grub
有两处需要注意。其一是Linux位置,可以通过 fdisk 查看,本例中为 sda8 。其二是 grub 安装。我这里 EFI 安装失败,所以指定了 i386-pc 这种老式方式。重启后问题圆满解决。
为了分析自己的驾驶行为,最近斥巨资35元在PDD上买了2个OBD盒子。结合Car Scanner得到了CSV格式的数据。在此基础上,计划利用R进行分析。
R语言教程 ,北京大学出品,适合快速上手。
R语言中变量命名规则与反引号的使用 ,阐述了R中变量名的自动转换问题。
data <- read.csv("2022-05-17+08-26-13.csv", header=TRUE, as.is=TRUE, check.names=FALSE)
程序中的选项header=TRUE
指明第一行作为变量名行, 选项as.is=TRUE
说明字符型列要原样读入而不是转换为因子(factor),check.names=FALSE
禁止变量名检查与自动转换。如果不禁用变量名检查,导入R的列名如下:
> colnames(data)
[1] "time"
[2] "发动机转速..rpm."
[3] "已耗燃油..L."
[4] "已耗燃油.总计...L."
[5] "平均速度..km.h."
[6] "平均速度..GPS...km.h."
[7] "气压..kPa."
[8] "氧传感器1宽范围.电流.mA...mA."
[9] "氧传感器1宽范围.等价比..."
[10] "燃料价格...."
[11] "燃料价格.总计....."
[12] "燃油平均消耗.升.100公里...L.100km."
[13] "燃油平均消耗.升.100公里..10.sec..L.100km."
[14] "燃油平均消耗.升.100公里..总计...L.100km."
[15] "燃油瞬时消耗.升.100公里...L.100km."
[16] "省油器.基于燃油系统状态和油门位置...."
[17] "瞬时发动机功率.根据燃油消耗...kW."
[18] "瞬时燃油消耗.升.小时...L.h."
[19] "节气门位置...."
[20] "计算增压..bar."
[21] "路程..km."
[22] "路程.总计...km."
[23] "车辆加速..g."
[24] "车速..km.h."
[25] "进气歧管绝对压力..kPa."
[26] "进气温度...."
[27] "速度..GPS...km.h."
[28] "高度..GPS...m."
[29] "Latitude"
[30] "Longtitude"
[31] "X"
禁用检查后,结果如下:
> colnames(data)
[1] "time"
[2] "发动机转速 (rpm)"
[3] "已耗燃油 (L)"
[4] "已耗燃油(总计) (L)"
[5] "平均速度 (km/h)"
[6] "平均速度 (GPS) (km/h)"
[7] "气压 (kPa)"
[8] "氧传感器1宽范围 电流(mA) (mA)"
[9] "氧传感器1宽范围 等价比 ()"
[10] "燃料价格 (¥)"
[11] "燃料价格(总计) (¥)"
[12] "燃油平均消耗(升/100公里) (L/100km)"
[13] "燃油平均消耗(升/100公里) 10 sec (L/100km)"
[14] "燃油平均消耗(升/100公里)(总计) (L/100km)"
[15] "燃油瞬时消耗(升/100公里) (L/100km)"
[16] "省油器(基于燃油系统状态和油门位置) ()"
[17] "瞬时发动机功率(根据燃油消耗) (kW)"
[18] "瞬时燃油消耗(升/小时) (L/h)"
[19] "节气门位置 (%)"
[20] "计算增压 (bar)"
[21] "路程 (km)"
[22] "路程(总计) (km)"
[23] "车辆加速 (g)"
[24] "车速 (km/h)"
[25] "进气歧管绝对压力 (kPa)"
[26] "进气温度 (℃)"
[27] "速度 (GPS) (km/h)"
[28] "高度 (GPS) (m)"
[29] "Latitude"
[30] "Longtitude"
[31] ""
禁用变量检查与转换后,可以不加考虑地通过列名调用指定列:
> data$"发动机转速 (rpm)"
[1] NA NA NA 911 910 NA NA 907 908 902 909 899 895 895
[15] 896 895 895 902 910 910 898 910 902 898 902 896 897 897
[29] 895 903 907 902 903 903 901 905 900 900 900 898 904 905
[43] 905 902 899 899 901 900 905 898 897 900 900 898 905 902
[57] 899 897 897 896 906 897 903 904 899 904 908 908 901 898
[71] 899 893 893 903 902 909 904 897 891 891 903 902 903 892
[85] 889 895 892 892 882 886 889 896 892 887 887 890 896 893
[99] 893 893 884 895 890 893 891 880 880 883 890 889 886 889
[113] 892 892 886 890 900 890 886 895 895 886 887 895 889 891
(数据为节选)
分析某一变量随时间变化趋势,首先尝试绘制折线图。这里有一个小小的问题:数据中的时间格式如下:
> data$time
[1] "08:26:19.571" "08:26:19.573" "08:26:19.575" "08:26:20.597"
[5] "08:26:20.771" "08:26:20.933" "08:26:21.100" "08:26:21.266"
[9] "08:26:21.424" "08:26:21.612" "08:26:21.769" "08:26:21.938"
这种格式的数据R不能直接使用,需要进行转换,即将字符串转换为R可以理解的时间。
显而易见,原始数据中的时间格式为hms
格式,R提供了一个同名的第三方包:
install.packages("hms")
如果没用用户权限,包就会安装在home下某一个目录内。
然后加载这个包:
library(hms)
进行类型转换:
x <- as_hms(data$time)
OBD通过采样读取数据流,受采样率限制,不可能在同一时间读取到全部参数,所以值缺失现象在样本数据中随处可见。为了绘制折线图,需要对缺失值进行适当处理。
library(hms)
rpm <- data.frame(x = data$time, y = data$"发动机转速 (rpm)")
rpm <- rpm[!is.na(rpm$y),]
plot(as_hms(rpm$x), rpm$y, type = "b")
然后就得到了一个比较简陋的发动机转速随时间变化折线图。由于数据采样比较频繁,不显示标点的”l”类型更合适。添加主标题,xy轴标题,得到的折线图好看了一些:
plot(as_hms(rpm$x), rpm$y, type = "l", main = "远景x3 pro cvt 发动机转速随时间变化折线图", xlab = "时间", ylab = "发动机转速(rpm)")
> max(data$"发动机转速 (rpm)", na.rm=TRUE)
[1] 1837
> min(data$"发动机转速 (rpm)", na.rm=TRUE)
[1] 724
> mean(data$"发动机转速 (rpm)", na.rm=TRUE)
[1] 1199.271
> quantile(data$"燃油平均消耗(升/100公里) (L/100km)", na.rm=TRUE)
0% 25% 50% 75% 100%
10.43989 11.06329 13.97581 31.61916 57746.89340
summary提供了更快捷的数据摘要:
> summary(data$"发动机转速 (rpm)")
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
724 895 1251 1199 1460 1837 1002
>
在整体数据的summary中,发现 高度 (GPS) (m) 的最小值为零:
高度 (GPS) (m)
Min. : 0.0
1st Qu.:144.4
Median :147.3
Mean :134.1
3rd Qu.:149.8
Max. :176.3
NA's :2690
结合实际,显然这些零值是错误的,应当视为缺失值一并处理:
> data$"高度 (GPS) (m)"[data$"高度 (GPS) (m)"==0] <- NA
> summary(data$"高度 (GPS) (m)")
Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
140.3 145.2 147.8 148.6 150.0 176.3 2780
剔除零值后数据变得更有意义了。
拓展阅读:如何理解R中因子(factor)的概念?,猴子的回答同时阐明了 因子 的概念。
library(hms)
rpm <- data.frame(x = data$time, y = data$”高度 (GPS) (m)”)
rpm <- rpm[!is.na(rpm$y),]
plot(as_hms(rpm$x), rpm$y, type = “l”, main = “高度随时间变化折线图”, xlab = “时间”, ylab = “高度”)
library(hms)
rpm <- data.frame(x = data$time, y = data$”燃油平均消耗(升/100公里) (L/100km)”)
rpm <- rpm[!is.na(rpm$y),]
rpm <- rpm[!is.na(quantile(rpm$y,probs=c(.3, .75),na.rm=TRUE)),]
plot(as_hms(rpm$x), rpm$y, type = “l”, main = “燃油平均消耗(升/100公里) (L/100km)”, xlab = “时间”, ylab = “燃油平均消耗(升/100公里) (L/100km)”)
y=log2(x)
x=2^y
Rust官方教程中Packages,Crates与Modules一章略有些晦涩,特别是Packages与Crates的关系。这部分翻来覆去读了几遍,结合别人项目和Rust Packages vs Crates大概弄懂了。
Package 为其中的最高单位:
$ cargo new my-project
Created binary (application) `my-project` package
执行cargo new
命令,便得到了一个package
,大概对应其他语言中的 project ?
Package 具备如下特点:
d
Rust官方教程读到智能指针一章就有些迷糊了,毕竟上次接触指针还是N年前的 谭浩强 C语言 XD 而且只看不练基础没法牢固,所以打算对前面章节进行一些实验,研究下可行的编程范例。
这个例子是对结构体的实验。之前用python时 字典 + 列表 足以应对绝大部分场景。Rust中 Vec 有些类似列表,不过 Vec 中成员类型要求一致。 Vec 提供了push和pop方法用于增删成员,也可以通过索引或者get方法调用成员。注意get方法返回 Option<&T> 类型需要自己match一下。
此外有几点需要留意:
fn add(self, s: &str) -> String {
所以对于一般 let s3 = s1 + &s2
的情形, s1 所有权会发生转移。如果要避免所有权转移的麻烦,使用format!
即可。
#[derive(Debug)]
struct Rect1 {
id: u64,
name: String,
}
impl Rect1 {
fn new(id:u64, name: String) -> Rect1 {
Rect1 {
id,
name,
}
}
}
fn main() {
let mut id: u64;
let mut name: String;
let mut clbox: Vec<Rect1> = Vec::new();
for i in 0..5 {
id = i;
name = "a".to_string() + &id.to_string();
//name = format!("{}{}", "a", &id.to_string());
//let tmp_rect = Rect1::new(id, name);
clbox.push(Rect1::new(id, name));
}
for item in &clbox {
println!("{} - {}", item.id, item.name);
}
println!("\n");
for item in &clbox {
println!("{:?}", item);
}
}
sudo pacman-key --init && sudo pacman-key --populate && sudo pacman -Syyu
网上随便搜来的,解决了问题。
Manjaro ARM 21.12 已发布了一段时间,照例测试了VIM2镜像。除了软件包例行更新外,引导方式发生了重大改变。在21.10及之前版本中,系统启动顺序为 BSP U-BOOT - Mainline U-BOOT - Linux Kernel ,21.12抛弃了 Mainline U-BOOT ,由 BSP U-BOOT 直接加载 Linux Kernel 。
理论上此次改动缩短了启动流程,项目维护成本更小。不过实际测试来看,取消 Mainline U-BOOT 后,系统暴露出一些问题:
问题1对于无头服务器影响轻微,即便是第一次开机初始化配置也可以通过SSH远程完成,完成初始化配置前root用户无密码可远程登录。
问题2只要不频繁重启主机影响也不大。除了更新内核外,必须重启的场景不多。关机基本不存在的,低功耗零噪音7X24开机运行无压力。
值得一提的是,放弃主线内核后,有线网卡MAC地址不会每次重启后变化了,所以不再需要用nmtui提供的mac address clone功能固定地址。
当然对于需要从低版本更新到21.12的盒子,还是建议在 /etc/pacman.conf 中,将 boot-vim2 添加到 IgnorePkg 中。直接更新 boot-vim2 会干掉 Image,而且不会更新启动配置文件,稳妥起见不要乱折腾为宜。
过去在R3300-M上进行过几次不成功的试验。无论是balbes150的Armbian 20.10还是目前使用的Manjaro Linux ARM,使用所提供的安装脚本均无法启动。最近发现论坛上名为pista一网友遇到类似问题并成功解决,看看我们能不能成功复现。
https://forum.armbian.com/topic/18902-s905-failed-to-boot-from-emmc/
Minix Neo U1 … S905, 2GB RAM / 16GB Flash ,搭配meson-gxbb-vega-s95-meta.dtb运行Armbian_20.10_Arm-64_bullseye_current_5.9.0.img。既然和R3300-M同为GXBB S905,那么如果Minix Neo U1可以从emmc启动linux,R3300-M也没有问题。
** No partition table - mmc 2 **
与R3300-M当时遇到的问题一致。
emmc分区保留前700MB,剩余空间分给ROOTFS,然后利用TF卡启动。在R3300-M上也曾试验成功,但我们的目的是完全脱离TF卡,于是pista开始了深入研究。
pista成功从EMMC分区启动了Armbian 20.10。关键所在是使用 mmc read 而不是 load/fatload 来加载 *kernel, ramdisk ,以及 dtb 。检查了Manjaro Linux ARM, /boot/boot.ini 内容如下:
ODROIDN2-UBOOT-CONFIG
#ODROIDC2-UBOOT-CONFIG
if test "${devtype}" = ""; then setenv devtype "mmc"; fi
if fatload ${devtype} ${devnum} 0x1000000 u-boot.ext; then go 0x1000000; fi;
看来需要想办法用 mmc read 替换 load/fatload 。
首先对emmc分区进行描述,pista的看起来这样:
blkdevparts=mmcblk1:209715200@1463812096(boot),-@1673528320(root)
209715200Byte对应200MByte,1463812096Byte对应1396MByte,1673528320约合1596MByte,并非精确匹配。
查询可知blkdevparts命令用法: https://www.kernel.org/doc/html/latest/block/cmdline-partition.html
通过学习,可知pista的分区描述为boot分区大小200MB(offset为1396MB,即emmc的前1396MB跳过,保留给为Amlogic的老uboot),这样EMMC的前1596MB就分配完毕了,209715200加上1463812096等于1673527296,比1673528320刚好小了1024。至此分区全貌一目了然:
1 - 1463812096 (前1396MB) 预留
1463812097 - 1673527296 boot分区,大小200MB
1673527297 - 1673528320 预留,大小1MB
1673528321 - root分区,占据剩余空间
pista为了保险起见,在EMMC分区头部保留了足足1396MB大小的空间。我们的R3300-M的EMMC容量总共才3728MB,可以适当减小预留空间,比如700MB。这样root分区大概有2.5GB空间可用,可以装下Manjaro ARM Minimal或者openwrt等无GUI界面的Linux发行版了。
pista没有给出具体命令,只是介绍了大概过程:
dd if=zImage of=/dev/mmcblk1p2 bs=512 seek=2859008 count=54841'
mmc read 0x08080000 0x2BA3FC 0xD639
Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 62500 500000 437501 213.6M c W95 FAT32 (LBA)
/dev/mmcblk0p2 500001 250347519 249847519 119.1G 83 Linux
利用 df -h 查看,BOOT_MNJRO 使用了54MB大小空间,故分配200MB应该够用。(Manjaro ARM分配了214MB)先回顾一下,我们之前为R3300-M刷入了ATV固件,目的是提升CPU主频;在TF卡上刷入了VIM2的Manjaro ARM Minimal 21.10镜像,并使用meson-gxbb-p201.dtb启动。随后,用linux-odroid替换了主线内核。配合编译WIFI驱动、更换软件源、设置NetworkManager等操作,现在Manjaro ARM已经能够稳定运行,为运行各种服务做好了充分准备。不过默认命令行界面略显简陋,下文将介绍如何用较少的硬件资源使Manjaro ARM Minimal看起来更现代、更好用。
nano是Manjaro ARM Minimal的默认文本编辑器,稍作修改使其更好用:
sudo pacman -Sy nano-syntax-highlighting
编辑 /etc/nanorc ,加入以下两行:
include "/usr/share/nano/*.nanorc"
include "/usr/share/nano-syntax-highlighting/*.nanorc"
重新登录后生效。
sudo pacman -Sy silver ttf-nerd-fonts-symbols
创建 ~/.config/silver/silver.toml 文件,内容如下:
[[left]]
name = "status"
color.background = "black"
color.foreground = "white"
[[left]]
name = "user"
color.background = "yellow"
color.foreground = "black"
[[left]]
name = "dir"
color.background = "blue"
color.foreground = "black"
[[left]]
name = "git"
color.background = "green"
color.foreground = "black"
[[left]]
name = "cmdtime"
color.background = "magenta"
color.foreground = "black"
然后修改 ~/.bashrc 文件。默认文件大概这样:
#
# ~/.bashrc
#
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
alias ls='ls --color=auto'
PS1='[\u@\h \W]\$ '
修改成这样:
#
# ~/.bashrc
#
# If not running interactively, don't do anything
[[ $- != *i* ]] && return
PS1='[\u@\h \W]\$ '
# configure silver command prompt
export SILVER_ICONS=nerd
source <(silver init)
# source bash aliases
source ~/.bash_aliases
现在还没有 ~/.bash_aliases ,手动创建一个,一会儿要用。
sudo pacman -Sy exa bat chafa
编辑 ~/.bash_aliases ,加入以下内容:
alias ls="exa -aglh --icons"
alias tree="exa --tree --icons"
alias cat="bat"
alias chafa="chafa -f sixel"
exa和bat分别是ls和cat的现代化替代。chafa比较有意思,可以将图片转换为在命令行终端中显示的字符画。
保存后,重新登录或者执行source ~/.bashrc
生效。
sudo pacman -Ss mc ranger
mc是老前辈,ranger是后生,根据个人喜好使用。
Manjaro ARM最近似乎用linux-odroid替换了linux-vim,执行pacman -Syu系统更新时会提示是否替换:
core/linux 5.15.5-1
core/linux-headers 5.15.5-1
core/linux-vim 5.14.10-1
core/linux-vim-headers 5.14.10-1
core/linux-odroid 5.15.3-1
core/linux-odroid-headers 5.15.3-1
更新后测试没问题,重启正常,关机没测不过应该没问题。主线内核有空可以测下。
另外测试无线仍然无法正常驱动,可以看到WIFI列表但是连接失败。