0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Arduino UNOでmap文で遊ぶ

Last updated at Posted at 2022-06-15

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

プログラム




// 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);


さらにおまけ

o_con547.jpg

さらにどうだ


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

0
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?