x 親切な人からコメントをいただいたので一番下までよんでね!!
目的
楽(らく)できそうだから
いままでは、ビット操作でごにょごにょ
していたけど容量に余裕がある場合にmap文を使う
例題のテーマは、よく使う3テーマとする
- 0~1024を0~256にする(サーボやPWM等)
p = map(s,0,1024,0,256); - 0~1024を5000mVに変換する。(浮動小数点を使わないやり方)
v = map(s,0,1024,0,5000); - 0~1024を3300mVに変換する。(浮動小数点を使わないやり方で3.3V系)
v = map(s,0,1024,0,3300);
難しいやり方は、参考に
map文
xは、入力
yは、出力
y = map(x,変換前最小,変換前最大,変換後最小,変換後最大);
プログラム
// MAP_0_5000_UNO_1
#include <Arduino.h>
//初期化
void setup() {
Serial.begin(9600);
}//setup
int s, v;
//メインループ
void loop() {
Serial.println("map(s,0,1024,0,256)");
s = 1024;
s = map(s, 0, 1024, 0, 256);
Serial.println(s);
Serial.println();
Serial.println("map(s,0,1024,0,5000)");
s = 1024;
s = map(s, 0, 1024, 0, 5000);
Serial.println(s);
Serial.println();
Serial.println("map(s,0,1024,0,3300)");
s = 1024;
s = map(s, 0, 1024, 0, 3300);
Serial.println(s);
Serial.println();
//4秒の待ち
delay(4000);
}//loop
標準c言語のプログラム
#include <stdio.h>
long map(long x, long in_min, long in_max, long out_min, long out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
int main(void){
int s,v;
printf("map(s,0,1024,0,256)\r\n");
s = 1024;
s = map(s,0,1024,0,256);
printf("%d\r\n",s);
printf("\r\n");
printf("map(s,0,1024,0,5000)\r\n");
s = 1024;
s = map(s,0,1024,0,5000);
printf("%d\r\n",s);
printf("\r\n");
printf("map(s,0,1024,0,3300)\r\n");
s = 1024;
s = map(s,0,1024,0,3300);
printf("%d\r\n",s);
printf("\r\n");
}
map(s,0,1024,0,256)
256
map(s,0,1024,0,5000)
5000
map(s,0,1024,0,3300)
3300
親切な人の難しい計算方法 ADC値1024を5000mvにする計算方法
固定二進小数点を上手に使うと上手く計算できる
5000は、
1 0011 1000 1000
小数点を任意に設定
1 0011 1.000 1000
小数点を右シフトした5000を掛けて40000にする
1024 = 39.0625 = 40000
10 0111 → 39
0001 → 0.0625
1024 * 39 = 39,936 (Arduino UNOのintではオーバー)
1024 * 0.0625 = 64
39,936 + 64 = 40000
40000 * 0.125 = 5000
都合よく勝手に改造
Serial.print( ( (unsigned int)0b100111 * (unsigned int)s + (s >> 4 ) ) >> 3);
おまけ
//V <- S*4.882 UNO +-1mV
Voltage = ((sensorValue * 8) + ( (sensorValue * 8) / 10 ) + ( (sensorValue * 2) / 100 )) / 10 + (sensorValue * 4);
さらにおまけ
さらにどうだ
1024 * 39.0625= 40000 40000/8=5000
1024 * 39 = 39936
1024 * 0.0625 = 64
40000 40000/8=5000
1024 * 16 = 16384 16384/8=2048
1024 * 23 = 23552
1024 * 0.0625 = 64
23616 23616/8=2952
5000
1024 * 2 =2048
1024 * 23 = 23552
1024 * 0.0625 = 64
23616 23616/8=2952
5000
5000 / 3300 = 1.5151...
3300 / 5000 = 0.66
5000*6 / 10 = 3000
5000*6 / 100 = 300
難しいやり方は、↓↓↓
2ビットの右シフト
map(x,0,1024,0,256);
難しい書き方
x = x >> 2;
センサーのADCの値を5V(mV)に直す
map(x,0,1024,0,5000);
難しい書き方
s=(s * 5000) >> 10;
5000は、
4096
512
256
128
8
1 << 0 = 1
1 << 1 = 2
1 << 2 = 4
1 << 3 = 8
1 << 4 = 16
1 << 5 = 32
1 << 6 = 64
1 << 7 = 128
1 << 8 = 256
1 << 9 = 512
1 << 10 = 1024
1 << 11 = 2048
1 << 12 = 4096
式は、(Arduino UNOには、乗算器があるから趣味)
x = ((x << 12)+(x << 9)+(x << 8)+(x << 7)+(x << 3))>>10;
1024 から 256
#include <stdio.h>
long map(long x, long in_min, long in_max, long out_min, long out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
int main(void){
int s = 1024;
s = map(s,0,1024,0,256);
printf("%d\r\n",s);
}
256
電圧変換
#include <stdio.h>
long map(long x, long in_min, long in_max, long out_min, long out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
int main(void){
int s = 1024;
s = map(s,0,1024,0,5000);
printf("%d\r\n",s);
}
5000
2022/6/18からの続き
Arduino UnoのADCの値1024を5000mVに変換する。
難しい書き方 (軽量コンパクト)
いろいろ (初期で70万台売れたArduinoユーザーの為に) 1日考えた
1024 * 4.882
32*32 = 1024
32 * 165.25 = 4992
32 / 4 = 8
32*4.882 = 156.25
(32*625) / 128 = 156.25
#include <stdio.h>
int main(void){
short s = 1024;
//v = s * 4.882 nearly equal +-1
short v = ((s>>5)*156) + ((s>>5)>>2) + (((s&0x1f)*625)>>7) ;
//short v2 = (((s&0x1f)*625)>>7);
printf("%d\r\n",v);
//printf("%d\r\n",v2);
// printf("%d\r\n",v+v2);
}
5000
続き
3.3V系 Arduino UNO でADC値1024を3300mVに変換する
32 * 32 = 1024
3300 / 103.125 = 32
32 * 103 = 3296
32 / 8 = 4
103.125 * 32 = 3300
(32 * 412) / 128 = 103
#include <stdio.h>
int main(void){
short s = 1024;
//v = s * 4.882 nearly equal +-1
short v = ((s>>5)*103) + ((s>>5)>>3) + (((s&0x1f)*412)>>7);
//short v2 = (((s&0x1f)*412)>>7);
printf("%d\r\n",v);
//printf("%d\r\n",v2);
//printf("%d\r\n",v+v2);
}
3300