Este es un problema bastante fundamental. Ocurre porque ese array está definida como una "variable global"
Una "variable global" es una variable definida fuera de cualquier función y accesible desde cualquier punto del código, desde el interior de cualquier función. Para el compilador, estas variables son simplemente lugares (direcciones) en la memoria RAM y para compilar el programa necesita saber cuánto espacio debe reservar y en qué sitio está cada variable.
Una posibilidad es usar "asignación dinámica de memoria" con la función malloc() pero se rumorea que el C de Arduino no maneja bien la función free()
Otra posibilidad es declarar esa variable dentro de una función, lo que crea esa variable en el stack, en "tiempo de ejecución". La declaración, por ejemplo int tabla[h][v]; tendría que estar, por ejemplo, dentro de loop()
loop()
{
int tabla[h][v];
...
...
}
pero eso impediría el acceso directo a ese array por parte de otras funciones y loop() tendría que proporcionarles ese acceso. Por ejemplo:
funcionJ(int valor)
{
....
}
loop(){
int tabla[h][v];
...
...
funcionJ(tabla[3][5]);
}
Otra posibilidad es usar un array (global) lo bastante grande que cubra el peor de los casos y luego utilizar algún tipo de índice que indique qué parte de la capacidad total del array se está empleando actualmente.