Arduino UNOでmap文で遊ぶ


x 親切な人からコメントをいただいたので一番下までよんでね!!


目的
楽(らく)できそうだから
いままでは、ビット操作でごにょごにょ
していたけど容量に余裕がある場合にmap文を使う

例題のテーマは、よく使う3テーマとする

1. 0～1024を0～256にする(サーボやPWM等)
p = map(s,0,1024,0,256);
2. 0～1024を5000mVに変換する。(浮動小数点を使わないやり方)
v = map(s,0,1024,0,5000);
3. 0～1024を3300mVに変換する。(浮動小数点を使わないやり方で3.3V系)
v = map(s,0,1024,0,3300);

難しいやり方は、参考に

```

map文

xは、入力
yは、出力


y = map(x,変換前最小,変換前最大,変換後最小,変換後最大);


```

![o_con539.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/75599d4f-9be7-6d70-f81f-1c6ab53af683.jpeg)



プログラム

```c++



// 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言語のプログラム

```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 


都合よく勝手に改造

```c++

Serial.print( ( (unsigned int)0b100111 * (unsigned int)s + (s >> 4 ) ) >> 3);

```

おまけ


```c++

  //V <- S*4.882 UNO +-1mV
  Voltage = ((sensorValue * 8) + ( (sensorValue * 8) / 10 ) + ( (sensorValue * 2) / 100 )) / 10  + (sensorValue * 4);


```

さらにおまけ

![o_con547.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/dcbfea0e-c0de-6faf-ecbf-03c8dbdaf6d3.jpeg)


さらにどうだ

```

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;

```


https://paiza.io/ja/projects/new?language=c


1024 から　256

```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 = 1024;


s = map(s,0,1024,0,256);

    
printf("%d\r\n",s);  
    
}




```

```

256

```

電圧変換

```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 = 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

```


```c++

#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

```

```c++


#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

```